1 /* 2 * Copyright (c)2004,2015 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 * fn_configure.c 36 * Configuration functions for installer. 37 * This includes both Configure the LiveCD Environment, and 38 * Configure an Installed System (there is considerable overlap.) 39 * $Id: fn_configure.c,v 1.82 2005/03/25 05:24:00 cpressey Exp $ 40 */ 41 42 #include <sys/stat.h> 43 #include <sys/types.h> 44 45 #include <ctype.h> 46 #include <dirent.h> 47 #include <fcntl.h> 48 #include <libgen.h> 49 #include <stdarg.h> 50 #include <stdio.h> 51 #include <stdlib.h> 52 #include <string.h> 53 #include <time.h> 54 #include <unistd.h> 55 56 #ifdef ENABLE_NLS 57 #include <libintl.h> 58 #define _(String) gettext (String) 59 #else 60 #define _(String) (String) 61 #endif 62 63 #include "libaura/mem.h" 64 #include "libaura/dict.h" 65 #include "libaura/fspred.h" 66 67 #include "libdfui/dfui.h" 68 #include "libdfui/system.h" 69 70 #include "libinstaller/commands.h" 71 #include "libinstaller/confed.h" 72 #include "libinstaller/diskutil.h" 73 #include "libinstaller/functions.h" 74 #include "libinstaller/package.h" 75 #include "libinstaller/uiutil.h" 76 77 #include "fn.h" 78 #include "flow.h" 79 #include "pathnames.h" 80 81 static const char *yes_to_y(const char *); 82 83 /** CONFIGURE FUNCTIONS **/ 84 85 #define PW_NOT_ALLOWED ":;,`~!@#$%^&*()+={}[]\\|/?<>'\" " 86 #define GECOS_NOT_ALLOWED ":,\\\"" 87 #define FILENAME_NOT_ALLOWED ":;`~!#$^&*()={}[]\\|?<>'\" " 88 #define MEMBERSHIPS_NOT_ALLOWED ":;`~!@#$%^&*()+={}[]\\|/?<>'\" " 89 90 void 91 fn_add_user(struct i_fn_args *a) 92 { 93 struct dfui_dataset *ds, *new_ds; 94 struct dfui_form *f; 95 struct dfui_response *r; 96 struct commands *cmds; 97 struct command *cmd; 98 const char *username, *home, *passwd_1, *passwd_2, *gecos; 99 const char *shell, *uid, *group, *groups; 100 int done = 0; 101 102 f = dfui_form_create( 103 "add_user", 104 _("Add user"), 105 _("Here you can add a user to an installed system.\n\n" 106 "You can leave the Home Directory, User ID, and Login Group " 107 "fields empty if you want these items to be automatically " 108 "allocated by the system.\n\n" 109 "Note: this user's password will appear in the install log. " 110 "If this is a problem, please add the user manually after " 111 "rebooting into the installed system instead."), 112 "", 113 "f", "username", _("Username"), 114 _("Enter the username the user will log in as"), "", 115 "f", "gecos", _("Real Name"), 116 _("Enter the real name (or GECOS field) of this user"), "", 117 "f", "passwd_1", _("Password"), 118 _("Enter the user's password (will not be displayed)"), "", 119 "p", "obscured", "true", 120 "f", "passwd_2", _("Password (Again)"), 121 _("Re-enter the user's password to confirm"), "", 122 "p", "obscured", "true", 123 "f", "shell", _("Shell"), 124 _("Enter the full path to the user's shell program"), "", 125 "f", "home", _("Home Directory"), 126 _("Enter the full path to the user's home directory, or leave blank"), "", 127 "f", "uid", _("User ID"), 128 _("Enter this account's numeric user id, or leave blank"), "", 129 "f", "group", _("Login Group"), 130 _("Enter the primary group for this account, or leave blank"), "", 131 "f", "groups", _("Other Group Memberships"), 132 _("Enter a comma-separated list of other groups " 133 "that this user should belong to"), "", 134 "a", "ok", _("Accept and Add"), "", "", 135 "a", "cancel", _("Return to Configure Menu"), "", "", 136 "p", "accelerator", "ESC", 137 NULL 138 ); 139 140 ds = dfui_dataset_new(); 141 dfui_dataset_celldata_add(ds, "username", ""); 142 dfui_dataset_celldata_add(ds, "gecos", ""); 143 dfui_dataset_celldata_add(ds, "passwd_1", ""); 144 dfui_dataset_celldata_add(ds, "passwd_2", ""); 145 dfui_dataset_celldata_add(ds, "shell", "/bin/tcsh"); 146 dfui_dataset_celldata_add(ds, "home", ""); 147 dfui_dataset_celldata_add(ds, "uid", ""); 148 dfui_dataset_celldata_add(ds, "group", ""); 149 dfui_dataset_celldata_add(ds, "groups", ""); 150 dfui_form_dataset_add(f, ds); 151 152 while (!done) { 153 if (!dfui_be_present(a->c, f, &r)) 154 abort_backend(); 155 156 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) { 157 done = 1; 158 dfui_response_free(r); 159 break; 160 } 161 162 new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r)); 163 dfui_form_datasets_free(f); 164 dfui_form_dataset_add(f, new_ds); 165 166 /* Fetch form field values. */ 167 168 username = dfui_dataset_get_value(new_ds, "username"); 169 home = dfui_dataset_get_value(new_ds, "home"); 170 gecos = dfui_dataset_get_value(new_ds, "gecos"); 171 shell = dfui_dataset_get_value(new_ds, "shell"); 172 passwd_1 = dfui_dataset_get_value(new_ds, "passwd_1"); 173 passwd_2 = dfui_dataset_get_value(new_ds, "passwd_2"); 174 uid = dfui_dataset_get_value(new_ds, "uid"); 175 group = dfui_dataset_get_value(new_ds, "group"); 176 groups = dfui_dataset_get_value(new_ds, "groups"); 177 178 if (strlen(username) == 0) { 179 inform(a->c, _("You must enter a username.")); 180 done = 0; 181 } else if (strcmp(passwd_1, passwd_2) != 0) { 182 /* Passwords don't match; tell the user. */ 183 inform(a->c, _("The passwords do not match.")); 184 done = 0; 185 } else if (!assert_clean(a->c, _("Username"), username, PW_NOT_ALLOWED) || 186 !assert_clean(a->c, _("Real Name"), gecos, GECOS_NOT_ALLOWED) || 187 !assert_clean(a->c, _("Password"), passwd_1, PW_NOT_ALLOWED) || 188 !assert_clean(a->c, _("Shell"), shell, FILENAME_NOT_ALLOWED) || 189 !assert_clean(a->c, _("Home Directory"), home, FILENAME_NOT_ALLOWED) || 190 !assert_clean(a->c, _("User ID"), uid, PW_NOT_ALLOWED) || 191 !assert_clean(a->c, _("Login Group"), group, PW_NOT_ALLOWED) || 192 !assert_clean(a->c, _("Group Memberships"), groups, MEMBERSHIPS_NOT_ALLOWED)) { 193 done = 0; 194 } else if (!is_program("%s%s", a->os_root, shell) && 195 strcmp(shell, "/nonexistent") != 0) { 196 inform(a->c, _("Chosen shell does not exist on the system.")); 197 done = 0; 198 } else { 199 cmds = commands_new(); 200 201 command_add(cmds, "%s%s %smnt/ /%s useradd " 202 "'%s' %s%s %s%s -c \"%s\" %s%s -s %s %s%s %s", 203 a->os_root, cmd_name(a, "CHROOT"), 204 a->os_root, cmd_name(a, "PW"), 205 username, 206 strlen(uid) == 0 ? "" : "-u ", uid, 207 strlen(group) == 0 ? "" : "-g ", group, 208 gecos, 209 strlen(home) == 0 ? "" : "-d ", home, 210 shell, 211 strlen(groups) == 0 ? "" : "-G ", groups, 212 (strlen(home) == 0 || !is_dir("%s", home)) ? 213 "-m -k /usr/share/skel" : ""); 214 215 cmd = command_add(cmds, "%s%s '%s' | " 216 "%s%s %smnt/ /%s usermod '%s' -h 0", 217 a->os_root, cmd_name(a, "ECHO"), 218 passwd_1, 219 a->os_root, cmd_name(a, "CHROOT"), 220 a->os_root, cmd_name(a, "PW"), 221 username); 222 command_set_desc(cmd, _("Setting password...")); 223 224 if (commands_execute(a, cmds)) { 225 inform(a->c, _("User `%s' was added."), username); 226 done = 1; 227 } else { 228 inform(a->c, _("User was not successfully added.")); 229 done = 0; 230 } 231 232 commands_free(cmds); 233 } 234 235 dfui_response_free(r); 236 } 237 238 dfui_form_free(f); 239 } 240 241 void 242 fn_root_passwd(struct i_fn_args *a) 243 { 244 struct dfui_dataset *ds, *new_ds; 245 struct dfui_form *f; 246 struct dfui_response *r; 247 struct commands *cmds; 248 struct command *cmd; 249 const char *root_passwd_1, *root_passwd_2; 250 int done = 0; 251 252 f = dfui_form_create( 253 "root_passwd", 254 _("Set Root Password"), 255 _("Here you can set the super-user (root) password.\n\n" 256 "Note: root's new password will appear in the install log. " 257 "If this is a problem, please set root's password manually " 258 "after rebooting into the installed system instead."), 259 "", 260 261 "f", "root_passwd_1", _("Root password"), 262 _("Enter the root password you would like to use"), "", 263 "p", "obscured", "true", 264 "f", "root_passwd_2", _("Root password again"), 265 _("Enter the root password again to confirm"), "", 266 "p", "obscured", "true", 267 268 "a", "ok", _("Accept and Set Password"), "", "", 269 "a", "cancel", _("Return to Configure Menu"), "", "", 270 "p", "accelerator", "ESC", 271 272 NULL 273 ); 274 275 ds = dfui_dataset_new(); 276 dfui_dataset_celldata_add(ds, "root_passwd_1", ""); 277 dfui_dataset_celldata_add(ds, "root_passwd_2", ""); 278 dfui_form_dataset_add(f, ds); 279 280 while (!done) { 281 if (!dfui_be_present(a->c, f, &r)) 282 abort_backend(); 283 284 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) { 285 new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r)); 286 dfui_form_datasets_free(f); 287 dfui_form_dataset_add(f, new_ds); 288 289 /* 290 * Fetch form field values. 291 */ 292 293 root_passwd_1 = dfui_dataset_get_value(new_ds, "root_passwd_1"); 294 root_passwd_2 = dfui_dataset_get_value(new_ds, "root_passwd_2"); 295 296 if (!assert_clean(a->c, _("Root password"), root_passwd_1, PW_NOT_ALLOWED)) { 297 done = 0; 298 } else if (strlen(root_passwd_1) == 0 && strlen(root_passwd_2) == 0) { 299 done = 0; 300 } else if (strcmp(root_passwd_1, root_passwd_2) == 0) { 301 /* 302 * Passwords match, so set the root password. 303 */ 304 cmds = commands_new(); 305 cmd = command_add(cmds, "%s%s '%s' | " 306 "%s%s %smnt/ /%s usermod root -h 0", 307 a->os_root, cmd_name(a, "ECHO"), 308 root_passwd_1, 309 a->os_root, cmd_name(a, "CHROOT"), 310 a->os_root, cmd_name(a, "PW")); 311 command_set_desc(cmd, _("Setting password...")); 312 if (commands_execute(a, cmds)) { 313 inform(a->c, _("The root password has been changed.")); 314 done = 1; 315 } else { 316 inform(a->c, _("An error occurred when " 317 "setting the root password.")); 318 done = 0; 319 } 320 commands_free(cmds); 321 } else { 322 /* 323 * Passwords don't match - tell the user, let them try again. 324 */ 325 inform(a->c, _("The passwords do not match.")); 326 done = 0; 327 } 328 } else { 329 /* 330 * Cancelled by user 331 */ 332 done = 1; 333 } 334 335 dfui_response_free(r); 336 } 337 338 dfui_form_free(f); 339 } 340 341 void 342 fn_get_passphrase(struct i_fn_args *a) 343 { 344 struct dfui_dataset *ds, *new_ds; 345 struct dfui_form *f; 346 struct dfui_response *r; 347 const char *passphrase_1, *passphrase_2; 348 int fd; 349 int done = 0; 350 351 f = dfui_form_create( 352 "crypt_passphrase", 353 _("Set Passphrase For Encryption"), 354 _("Please specify the passphrase to be used for the encrypted " 355 "filesystems.\n\n" 356 "Please note that in the LiveCD environment the keymap is set to " 357 "\"US ISO\". " 358 "If you prefer a different keymap for entering the passphrase " 359 "here, you will need to set it manually using kbdcontrol(1)."), 360 "", 361 362 "f", "passphrase_1", _("Passphrase"), 363 _("Enter the passphrase you would like to use for encryption"), "", 364 "p", "obscured", "true", 365 "f", "passphrase_2", _("Passphrase again"), 366 _("Enter the passphrase again to confirm"), "", 367 "p", "obscured", "true", 368 369 "a", "ok", _("Accept and Set Passphrase"), "", "", 370 "p", "accelerator", "ESC", 371 372 NULL 373 ); 374 375 ds = dfui_dataset_new(); 376 dfui_dataset_celldata_add(ds, "passphrase_1", ""); 377 dfui_dataset_celldata_add(ds, "passphrase_2", ""); 378 dfui_form_dataset_add(f, ds); 379 380 while (!done) { 381 if (!dfui_be_present(a->c, f, &r)) 382 abort_backend(); 383 384 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) { 385 new_ds = dfui_dataset_dup(dfui_response_dataset_get_first(r)); 386 dfui_form_datasets_free(f); 387 dfui_form_dataset_add(f, new_ds); 388 389 /* 390 * Fetch form field values. 391 */ 392 393 passphrase_1 = dfui_dataset_get_value(new_ds, "passphrase_1"); 394 passphrase_2 = dfui_dataset_get_value(new_ds, "passphrase_2"); 395 396 if (strlen(passphrase_1) == 0 && strlen(passphrase_2) == 0) { 397 done = 0; 398 } else if (strcmp(passphrase_1, passphrase_2) == 0) { 399 /* 400 * Passphrases match, write it out. 401 */ 402 fd = open("/tmp/t1", O_RDWR | O_CREAT | O_TRUNC, 403 S_IRUSR); 404 if (fd != -1) { 405 write(fd, passphrase_1, strlen(passphrase_1)); 406 close(fd); 407 done = 1; 408 } else { 409 inform(a->c, _("write() error")); 410 done = 0; 411 } 412 } else { 413 /* 414 * Passphrases don't match, tell the user, 415 * let them try again. 416 */ 417 inform(a->c, _("The passphrases do not match.")); 418 done = 0; 419 } 420 } 421 422 dfui_response_free(r); 423 } 424 425 dfui_form_free(f); 426 } 427 428 void 429 fn_install_packages(struct i_fn_args *a) 430 { 431 FILE *pfp; 432 struct commands *cmds; 433 struct dfui_celldata *cd; 434 struct dfui_dataset *ds; 435 struct dfui_field *fi; 436 struct dfui_form *f; 437 struct dfui_response *r; 438 char command[256]; 439 char pkg_name[256]; 440 char msg_buf[1][1024]; 441 struct aura_dict *seen; 442 443 snprintf(msg_buf[0], sizeof(msg_buf[0]), 444 _("Select optional software packages that you want " 445 "installed on this system. This form lists only the " 446 "software packages installed on the LiveCD; thousands " 447 "more are available via the internet once %s " 448 "is installed."), 449 OPERATING_SYSTEM_NAME); 450 451 f = dfui_form_create( 452 "install_packages", 453 _("Install Packages"), 454 msg_buf[0], 455 "", 456 457 "p", "special", "dfinstaller_install_packages", 458 459 NULL 460 ); 461 462 ds = dfui_dataset_new(); 463 snprintf(command, 256, "ls %svar/db/pkg", a->os_root); 464 if ((pfp = popen(command, "r")) != NULL) { 465 while (fgets(pkg_name, 255, pfp) != NULL) { 466 while (strlen(pkg_name) > 0 && 467 isspace(pkg_name[strlen(pkg_name) - 1])) { 468 pkg_name[strlen(pkg_name) - 1] = '\0'; 469 } 470 fi = dfui_form_field_add(f, pkg_name, 471 dfui_info_new(pkg_name, "", "")); 472 dfui_field_property_set(fi, "control", "checkbox"); 473 dfui_dataset_celldata_add(ds, 474 pkg_name, "Y"); 475 } 476 pclose(pfp); 477 } 478 dfui_form_dataset_add(f, ds); 479 480 dfui_form_action_add(f, "ok", 481 dfui_info_new(_("Accept and Install"), "", "")); 482 dfui_form_action_add(f, "cancel", 483 dfui_info_new(_("Return to Configure Menu"), "", "")); 484 485 if (!dfui_be_present(a->c, f, &r)) 486 abort_backend(); 487 488 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) { 489 cmds = commands_new(); 490 seen = aura_dict_new(23, AURA_DICT_HASH); 491 492 cd = dfui_dataset_celldata_get_first(dfui_response_dataset_get_first(r)); 493 494 while (cd != NULL) { 495 strlcpy(pkg_name, dfui_celldata_get_field_id(cd), 256); 496 if (!strcasecmp(dfui_celldata_get_value(cd), "Y")) { 497 if (!pkg_copy(a, cmds, pkg_name, seen)) { 498 inform(a->c, _("Couldn't install package `%s'."), pkg_name); 499 break; 500 } 501 } 502 cd = dfui_celldata_get_next(cd); 503 } 504 505 if (!commands_execute(a, cmds)) { 506 inform(a->c, _("Packages were not fully installed.")); 507 } else { 508 inform(a->c, _("Packages were successfully installed!")); 509 } 510 511 aura_dict_free(seen); 512 commands_free(cmds); 513 } 514 515 dfui_form_free(f); 516 dfui_response_free(r); 517 } 518 519 void 520 fn_remove_packages(struct i_fn_args *a) 521 { 522 FILE *pfp; 523 struct commands *cmds; 524 struct dfui_celldata *cd; 525 struct dfui_dataset *ds; 526 struct dfui_field *fi; 527 struct dfui_form *f; 528 struct dfui_response *r; 529 char command[256]; 530 char pkg_name[256]; 531 struct aura_dict *seen; 532 533 f = dfui_form_create( 534 "remove_packages", 535 _("Remove Packages"), 536 _("Select the installed software packages that you want " 537 "removed from this system."), 538 "", 539 540 "p", "special", "dfinstaller_remove_packages", 541 542 NULL 543 ); 544 545 ds = dfui_dataset_new(); 546 snprintf(command, 256, "ls %smnt/var/db/pkg", a->os_root); 547 if ((pfp = popen(command, "r")) != NULL) { 548 while (fgets(pkg_name, 255, pfp)) { 549 pkg_name[strlen(pkg_name) - 1] = '\0'; 550 fi = dfui_form_field_add(f, pkg_name, 551 dfui_info_new(pkg_name, "", "")); 552 dfui_field_property_set(fi, "control", "checkbox"); 553 dfui_dataset_celldata_add(ds, 554 pkg_name, "N"); 555 } 556 pclose(pfp); 557 } 558 dfui_form_dataset_add(f, ds); 559 560 dfui_form_action_add(f, "ok", 561 dfui_info_new(_("Accept and Remove"), "", "")); 562 dfui_form_action_add(f, "cancel", 563 dfui_info_new(_("Return to Configure Menu"), "", "")); 564 565 if (!dfui_be_present(a->c, f, &r)) 566 abort_backend(); 567 568 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) { 569 cmds = commands_new(); 570 seen = aura_dict_new(23, AURA_DICT_HASH); 571 572 cd = dfui_dataset_celldata_get_first(dfui_response_dataset_get_first(r)); 573 574 while (cd != NULL) { 575 strlcpy(pkg_name, dfui_celldata_get_field_id(cd), 256); 576 if (!strcasecmp(dfui_celldata_get_value(cd), "Y")) { 577 if (!pkg_remove(a, cmds, pkg_name, seen)) { 578 inform(a->c, _("Couldn't remove package `%s'."), pkg_name); 579 break; 580 } 581 } 582 cd = dfui_celldata_get_next(cd); 583 } 584 585 if (!commands_execute(a, cmds)) { 586 inform(a->c, _("Packages were not fully removed.")); 587 } else { 588 inform(a->c, _("Packages were successfully removed.")); 589 } 590 591 aura_dict_free(seen); 592 commands_free(cmds); 593 } 594 595 dfui_form_free(f); 596 dfui_response_free(r); 597 } 598 599 /** LIVECD UTILITIES FUNCTIONS **/ 600 601 /* 602 * String returned by this function must be deallocated by the caller. 603 */ 604 char * 605 fn_select_file(const char *title, const char *desc, const char *help, const char *cancel, 606 const char *dir, const char *ext, const struct i_fn_args *a) 607 { 608 DIR *d; 609 struct dfui_form *f; 610 struct dfui_action *k; 611 struct dfui_response *r; 612 struct dirent *de; 613 char *s; 614 struct aura_dict *dict; 615 char *rk; 616 size_t rk_len; 617 618 f = dfui_form_create( 619 "select_file", 620 title, desc, help, 621 "p", "role", "menu", 622 NULL 623 ); 624 625 dict = aura_dict_new(1, AURA_DICT_SORTED_LIST); 626 d = opendir(dir); 627 while ((de = readdir(d)) != NULL) { 628 if (strcmp(de->d_name, ".") == 0 || 629 strcmp(de->d_name, "..") == 0 || 630 strstr(de->d_name, ext) == NULL) 631 continue; 632 aura_dict_store(dict, de->d_name, strlen(de->d_name) + 1, "", 1); 633 } 634 closedir(d); 635 636 aura_dict_rewind(dict); 637 while (!aura_dict_eof(dict)) { 638 aura_dict_get_current_key(dict, (void **)&rk, &rk_len), 639 dfui_form_action_add(f, rk, 640 dfui_info_new(rk, "", "")); 641 aura_dict_next(dict); 642 } 643 aura_dict_free(dict); 644 645 k = dfui_form_action_add(f, "cancel", 646 dfui_info_new(cancel, "", "")); 647 dfui_action_property_set(k, "accelerator", "ESC"); 648 649 if (!dfui_be_present(a->c, f, &r)) 650 abort_backend(); 651 652 s = aura_strdup(dfui_response_get_action_id(r)); 653 654 dfui_form_free(f); 655 dfui_response_free(r); 656 657 return(s); 658 } 659 660 void 661 fn_set_kbdmap(struct i_fn_args *a) 662 { 663 struct commands *cmds; 664 char *s; 665 char filename[256], keymapname[256]; 666 667 s = fn_select_file(_("Select Keyboard Map"), 668 _("Select a keyboard map appropriate to your keyboard layout."), 669 "", _("Return to Utilities Menu"), "/usr/share/syscons/keymaps", 670 ".kbd", a); 671 672 if (strcmp(s, "cancel") != 0) { 673 cmds = commands_new(); 674 command_add(cmds, "%s%s -l " 675 "/usr/share/syscons/keymaps/%s < /dev/ttyv0", 676 a->os_root, cmd_name(a, "KBDCONTROL"), 677 s); 678 if (commands_execute(a, cmds)) { 679 snprintf(filename, 256, "/usr/share/syscons/keymaps/%s", s); 680 snprintf(keymapname, 256, "%s", filename_noext(basename(filename))); 681 config_var_set(rc_conf, "keymap", keymapname); 682 } else { 683 inform(a->c, _("Keyboard map not successfully set.")); 684 } 685 commands_free(cmds); 686 } 687 688 free(s); 689 } 690 691 void 692 fn_set_vidfont(struct i_fn_args *a) 693 { 694 struct commands *cmds; 695 char *s; 696 char filename[256], variable[256], fontname[256]; 697 int by = 0; 698 699 700 s = fn_select_file(_("Select Console Font"), 701 _("Select a font appropriate to your video monitor and language."), 702 "", _("Return to Utilities Menu"), "/usr/share/syscons/fonts", 703 ".fnt", a); 704 705 if (strcmp(s, "cancel") != 0) { 706 cmds = commands_new(); 707 command_add(cmds, "%s%s -f " 708 "/usr/share/syscons/fonts/%s < /dev/ttyv0", 709 a->os_root, cmd_name(a, "VIDCONTROL"), 710 s); 711 if (commands_execute(a, cmds)) { 712 if (strstr(s, "8x16") != NULL) 713 by = 16; 714 else if (strstr(s, "8x14") != NULL) 715 by = 14; 716 else 717 by = 8; 718 719 snprintf(variable, 256, "font8x%d", by); 720 snprintf(filename, 256, "/usr/share/syscons/fonts/%s", s); 721 snprintf(fontname, 256, "%s", filename_noext(basename(filename))); 722 config_var_set(rc_conf, variable, fontname); 723 724 } else { 725 inform(a->c, _("Video font not successfully set.")); 726 } 727 commands_free(cmds); 728 } 729 730 free(s); 731 } 732 733 void 734 fn_set_scrnmap(struct i_fn_args *a) 735 { 736 struct commands *cmds; 737 char *s; 738 char filename[256], scrnmapname[256]; 739 740 s = fn_select_file(_("Select Screen Map"), 741 _("Select a mapping for translating characters as they appear " 742 "on your video console screen."), 743 "", _("Return to Utilities Menu"), "/usr/share/syscons/scrnmaps", 744 ".scm", a); 745 746 if (strcmp(s, "cancel") != 0) { 747 cmds = commands_new(); 748 command_add(cmds, "%s%s -l " 749 "/usr/share/syscons/scrnmaps/%s < /dev/ttyv0", 750 a->os_root, cmd_name(a, "VIDCONTROL"), 751 s); 752 if (commands_execute(a, cmds)) { 753 snprintf(filename, 256, "/usr/share/syscons/scrnmaps/%s", s); 754 snprintf(scrnmapname, 256, "%s", filename_noext(basename(filename))); 755 config_var_set(rc_conf, "scrnmap", scrnmapname); 756 } else { 757 inform(a->c, _("Video font not successfully set.")); 758 } 759 commands_free(cmds); 760 } 761 free(s); 762 } 763 764 void 765 fn_set_timezone(struct i_fn_args *a) 766 { 767 struct commands *cmds; 768 char *s = NULL; 769 char current_path[256], selection[256], temp[256]; 770 int found_file = 0; 771 int result; 772 773 result = dfui_be_present_dialog(a->c, _("Local or UTC (Greenwich Mean Time) clock"), 774 _("Yes|No"), 775 _("Is this machine's CMOS clock set to UTC?\n\n" 776 "If it is set to local time, or you don't know, please choose NO here!")); 777 if (result < 1) 778 abort_backend(); 779 780 cmds = commands_new(); 781 switch (result) { 782 case 1: 783 command_add(cmds, "%s%s -f %s%setc/wall_cmos_clock", 784 a->os_root, cmd_name(a, "RM"), 785 a->os_root, a->cfg_root); 786 break; 787 case 2: 788 command_add(cmds, "%s%s %s%setc/wall_cmos_clock", 789 a->os_root, cmd_name(a, "TOUCH"), 790 a->os_root, a->cfg_root); 791 break; 792 } 793 commands_execute(a, cmds); 794 795 snprintf(current_path, 256, "%s%susr/share/zoneinfo", 796 a->os_root, a->cfg_root); 797 while (!found_file) { 798 if (s != NULL) 799 free(s); 800 s = fn_select_file(_("Select Time Zone"), 801 _("Select a Time Zone appropriate to your physical location."), 802 "", _("Return to Utilities Menu"), current_path, 803 "", a); 804 if (is_dir("%s/%s", current_path, s)) { 805 snprintf(temp, 256, "%s/%s", current_path, s); 806 strlcpy(current_path, temp, 256); 807 } else { 808 if (is_file("%s/%s", current_path, s)) { 809 snprintf(selection, 256, "%s/%s", current_path, s); 810 found_file = 1; 811 } 812 if (strcmp(s, "cancel") == 0) { 813 strlcpy(selection, "cancel", 256); 814 found_file = 1; 815 } 816 } 817 } 818 free(s); 819 820 if (strcmp(selection, "cancel") != 0) { 821 command_add(cmds, "%s%s %s %s%setc/localtime", 822 a->os_root, cmd_name(a, "CP"), 823 selection, 824 a->os_root, a->cfg_root); 825 if (commands_execute(a, cmds)) { 826 inform(a->c, _("The Time Zone has been set to %s."), selection); 827 setenv("TZ", selection, 1); 828 tzset(); 829 } 830 } 831 commands_free(cmds); 832 } 833 834 void 835 fn_assign_datetime(struct i_fn_args *a) 836 { 837 struct commands *cmds; 838 struct dfui_dataset *ds, *new_ds; 839 struct dfui_form *f; 840 struct dfui_response *r; 841 struct tm *tp; 842 char temp[256]; 843 int year, month, dayofmonth, hour, minutes; 844 int valid = 1; 845 time_t now; 846 847 now = time(NULL); 848 tp = localtime(&now); 849 850 f = dfui_form_create( 851 "set_datetime", 852 _("Set Time/Date"), 853 _("Enter the date-time in your timezone."), 854 "", 855 856 "f", "year", _("Enter year"), 857 _("Enter the current year (e.g. `2004')"), "", 858 "f", "month", _("Month"), 859 _("Enter the current month (e.g. `07')"), "", 860 "f", "dayofmonth", "dayofmonth", 861 _("Enter the current day of month (e.g. `30')"), "", 862 "f", "hour", "hour", 863 _("Enter the current hour (e.g. `07')"), "", 864 "f", "minutes", "minutes", 865 _("Enter the current minutes (e.g. `59')"), "", 866 867 "a", "ok", _("OK"), "", "", 868 "a", "cancel", _("Cancel"), "", "", 869 "p", "accelerator", "ESC", 870 871 NULL 872 ); 873 874 ds = dfui_dataset_new(); 875 snprintf(temp, 256, "%i", (tp->tm_year+1900)); 876 dfui_dataset_celldata_add(ds, "year", temp); 877 snprintf(temp, 256, "%i", (tp->tm_mon+1)); 878 dfui_dataset_celldata_add(ds, "month", temp); 879 snprintf(temp, 256, "%i", tp->tm_mday); 880 dfui_dataset_celldata_add(ds, "dayofmonth", temp); 881 snprintf(temp, 256, "%i", tp->tm_hour); 882 dfui_dataset_celldata_add(ds, "hour", temp); 883 snprintf(temp, 256, "%i", tp->tm_min); 884 dfui_dataset_celldata_add(ds, "minutes", temp); 885 dfui_form_dataset_add(f, ds); 886 887 if (!dfui_be_present(a->c, f, &r)) 888 abort_backend(); 889 890 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) { 891 new_ds = dfui_response_dataset_get_first(r); 892 893 if ((year = atoi(dfui_dataset_get_value(new_ds, "year"))) <= 0) 894 valid = 0; 895 month = atoi(dfui_dataset_get_value(new_ds, "month")); 896 if (month < 1 || month > 12) 897 valid = 0; 898 dayofmonth = atoi(dfui_dataset_get_value(new_ds, "dayofmonth")); 899 if (dayofmonth < 1 || dayofmonth > 31) 900 valid = 0; 901 hour = atoi(dfui_dataset_get_value(new_ds, "hour")); 902 if (hour < 0 || hour > 23) 903 valid = 0; 904 minutes = atoi(dfui_dataset_get_value(new_ds, "minutes")); 905 if (minutes < 0 || minutes > 59) 906 valid = 0; 907 908 if (valid) { 909 cmds = commands_new(); 910 command_add(cmds, "%s%s -n %04d%02d%02d%02d%02d", 911 a->os_root, cmd_name(a, "DATE"), 912 year, month, dayofmonth, hour, minutes); 913 if (commands_execute(a, cmds)) { 914 inform(a->c, _("The date and time have been set.")); 915 } 916 commands_free(cmds); 917 } else { 918 inform(a->c, _("Please enter numbers within acceptable ranges " 919 "for year, month, day of month, hour, and minute.")); 920 } 921 } 922 } 923 924 void 925 fn_assign_hostname_domain(struct i_fn_args *a) 926 { 927 struct dfui_form *f; 928 struct dfui_response *r; 929 struct dfui_dataset *ds, *new_ds; 930 struct config_vars *resolv_conf; 931 const char *domain, *hostname; 932 char *fqdn; 933 934 f = dfui_form_create( 935 "set_hostname_domain", 936 _("Set Hostname/Domain"), 937 _("Please enter this machine's hostname and domain name."), 938 "", 939 940 "f", "hostname", _("Hostname"), 941 _("Enter the Hostname (e.g. `machine')"), "", 942 "f", "domain", _("Domain"), 943 _("Enter the Domain Name (e.g. `network.lan')"), "", 944 945 "a", "ok", _("OK"), "", "", 946 "a", "cancel", _("Cancel"), "", "", 947 "p", "accelerator", "ESC", 948 949 NULL 950 ); 951 952 ds = dfui_dataset_new(); 953 dfui_dataset_celldata_add(ds, "hostname", ""); 954 dfui_dataset_celldata_add(ds, "domain", ""); 955 dfui_form_dataset_add(f, ds); 956 957 if (!dfui_be_present(a->c, f, &r)) 958 abort_backend(); 959 960 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) { 961 new_ds = dfui_response_dataset_get_first(r); 962 963 hostname = dfui_dataset_get_value(new_ds, "hostname"); 964 domain = dfui_dataset_get_value(new_ds, "domain"); 965 if (strlen(domain) == 0) 966 asprintf(&fqdn, "%s", hostname); 967 else 968 asprintf(&fqdn, "%s.%s", hostname, domain); 969 970 resolv_conf = config_vars_new(); 971 972 config_var_set(rc_conf, "hostname", fqdn); 973 config_var_set(resolv_conf, "search", domain); 974 config_vars_write(resolv_conf, CONFIG_TYPE_RESOLV, 975 "%s%setc/resolv.conf", a->os_root, a->cfg_root); 976 977 config_vars_free(resolv_conf); 978 979 free(fqdn); 980 } 981 982 dfui_form_free(f); 983 dfui_response_free(r); 984 } 985 986 void 987 fn_assign_ip(struct i_fn_args *a) 988 { 989 FILE *p; 990 struct commands *cmds; 991 struct command *cmd; 992 struct config_vars *resolv_conf; 993 struct dfui_dataset *ds, *new_ds; 994 struct dfui_form *f; 995 struct dfui_action *k; 996 struct dfui_response *r; 997 const char *domain, *hostname; 998 const char *interface_ip, *interface_netmask, *defaultrouter, *dns_resolver; 999 char *string, *string1; 1000 char *word; 1001 char interface[256]; 1002 char line[256]; 1003 int write_config = 0; 1004 1005 /* 1006 * Get interface list. 1007 */ 1008 p = popen("/sbin/ifconfig -l", "r"); 1009 /* XXX it's possible (though extremely unlikely) this will fail. */ 1010 while (fgets(line, 255, p) != NULL) 1011 line[strlen(line) - 1] = '\0'; 1012 1013 pclose(p); 1014 1015 f = dfui_form_create( 1016 "assign_ip", 1017 _("Assign IP Address"), 1018 _("Please select which interface you would like to configure:"), 1019 "", 1020 "p", "role", "menu", 1021 NULL 1022 ); 1023 1024 /* Loop through array. */ 1025 word = strtok(line, " \t"); 1026 while (word != NULL) { 1027 dfui_form_action_add(f, word, 1028 dfui_info_new(word, "", "")); 1029 word = strtok(NULL, " "); 1030 } 1031 1032 k = dfui_form_action_add(f, "cancel", 1033 dfui_info_new("Cancel", "", "")); 1034 dfui_action_property_set(k, "accelerator", "ESC"); 1035 1036 if (!dfui_be_present(a->c, f, &r)) 1037 abort_backend(); 1038 1039 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) { 1040 dfui_form_free(f); 1041 dfui_response_free(r); 1042 return; 1043 } 1044 1045 strlcpy(interface, dfui_response_get_action_id(r), 256); 1046 1047 resolv_conf = config_vars_new(); 1048 1049 switch (dfui_be_present_dialog(a->c, _("Use DHCP?"), 1050 _("Use DHCP|Configure Manually"), 1051 _("DHCP allows the interface to automatically obtain " 1052 "an IP address from a nearby DHCP server.\n\n" 1053 "Would you like to enable DHCP for %s?"), interface)) { 1054 case 1: 1055 asprintf(&string, "ifconfig_%s", interface); 1056 1057 cmds = commands_new(); 1058 cmd = command_add(cmds, "%s%s dhclient", 1059 a->os_root, cmd_name(a, "KILLALL")); 1060 command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE); 1061 command_add(cmds, "%s%s %s", 1062 a->os_root, cmd_name(a, "DHCLIENT"), 1063 interface); 1064 if (commands_execute(a, cmds)) { 1065 /* XXX sleep(3); */ 1066 show_ifconfig(a->c, interface); 1067 write_config = 1; 1068 } else { 1069 switch (dfui_be_present_dialog(a->c, _("DHCP Failure"), 1070 _("Yes|No"), 1071 _("Warning: could not enable dhclient for %s.\n\n" 1072 "Write the corresponding settings to rc.conf " 1073 "anyway?"), interface)) { 1074 case 1: 1075 write_config = 1; 1076 break; 1077 case 2: 1078 write_config = 0; 1079 break; 1080 default: 1081 abort_backend(); 1082 } 1083 } 1084 commands_free(cmds); 1085 config_var_set(rc_conf, string, "DHCP"); 1086 free(string); 1087 break; 1088 case 2: 1089 dfui_form_free(f); 1090 dfui_response_free(r); 1091 f = dfui_form_create( 1092 "assign_ip", 1093 _("Assign IP Address"), 1094 _("Configuring Interface:"), 1095 "", 1096 1097 "f", "interface_ip", _("IP Address"), 1098 _("Enter the IP Address you would like to use"), "", 1099 "f", "interface_netmask", _("Netmask"), 1100 _("Enter the netmask of the IP address"), "", 1101 "f", "defaultrouter", _("Default Router"), 1102 _("Enter the IP address of the default router"), "", 1103 "f", "dns_resolver", _("Primary DNS Server"), 1104 _("Enter the IP address of primary DNS Server"), "", 1105 "f", "hostname", _("Hostname"), 1106 _("Enter the Hostname"), "", 1107 "f", "domain", _("Domain"), 1108 _("Enter the Domain Name"), "", 1109 1110 "a", "ok", _("Configure Interface"), 1111 "", "", 1112 "a", "cancel", _("Return to Utilities Menu"), 1113 "", "", 1114 "p", "accelerator", "ESC", 1115 1116 NULL 1117 ); 1118 1119 ds = dfui_dataset_new(); 1120 dfui_dataset_celldata_add(ds, "interface_netmask", ""); 1121 dfui_dataset_celldata_add(ds, "defaultrouter", ""); 1122 dfui_dataset_celldata_add(ds, "dns_resolver", ""); 1123 dfui_dataset_celldata_add(ds, "hostname", ""); 1124 dfui_dataset_celldata_add(ds, "domain", ""); 1125 dfui_dataset_celldata_add(ds, "interface_ip", ""); 1126 dfui_form_dataset_add(f, ds); 1127 1128 if (!dfui_be_present(a->c, f, &r)) 1129 abort_backend(); 1130 1131 if (strcmp(dfui_response_get_action_id(r), "ok") == 0) { 1132 new_ds = dfui_response_dataset_get_first(r); 1133 1134 interface_ip = dfui_dataset_get_value( 1135 new_ds, "interface_ip"); 1136 interface_netmask = dfui_dataset_get_value( 1137 new_ds, "interface_netmask"); 1138 defaultrouter = dfui_dataset_get_value( 1139 new_ds, "defaultrouter"); 1140 dns_resolver = dfui_dataset_get_value( 1141 new_ds, "dns_resolver"); 1142 hostname = dfui_dataset_get_value( 1143 new_ds, "hostname"); 1144 domain = dfui_dataset_get_value( 1145 new_ds, "domain"); 1146 1147 asprintf(&string, "ifconfig_%s", interface); 1148 asprintf(&string1, "inet %s netmask %s", 1149 interface_ip, interface_netmask); 1150 1151 cmds = commands_new(); 1152 command_add(cmds, "%s%s %s %s netmask %s", 1153 a->os_root, cmd_name(a, "IFCONFIG"), 1154 interface, interface_ip, interface_netmask); 1155 command_add(cmds, "%s%s add default %s", 1156 a->os_root, cmd_name(a, "ROUTE"), 1157 defaultrouter); 1158 1159 if (commands_execute(a, cmds)) { 1160 /* XXX sleep(3); */ 1161 show_ifconfig(a->c, interface); 1162 write_config = 1; 1163 } else { 1164 switch (dfui_be_present_dialog(a->c, 1165 _("ifconfig Failure"), 1166 _("Yes|No"), 1167 _("Warning: could not assign IP address " 1168 "or default gateway.\n\n" 1169 "Write the corresponding settings to " 1170 "rc.conf anyway?"))) { 1171 case 1: 1172 write_config = 1; 1173 break; 1174 case 2: 1175 write_config = 0; 1176 break; 1177 default: 1178 abort_backend(); 1179 } 1180 } 1181 commands_free(cmds); 1182 1183 config_var_set(rc_conf, string, string1); 1184 config_var_set(rc_conf, "defaultrouter", defaultrouter); 1185 1186 free(string); 1187 free(string1); 1188 1189 asprintf(&string, "%s.%s", hostname, domain); 1190 config_var_set(rc_conf, "hostname", string); 1191 free(string); 1192 1193 config_var_set(resolv_conf, "search", domain); 1194 config_var_set(resolv_conf, "nameserver", dns_resolver); 1195 } 1196 break; 1197 default: 1198 abort_backend(); 1199 } 1200 1201 if (write_config) { 1202 /* 1203 * Save out changes to /etc/rc.conf and /etc/resolv.conf. 1204 */ 1205 config_vars_write(resolv_conf, CONFIG_TYPE_RESOLV, 1206 "%s%setc/resolv.conf", a->os_root, a->cfg_root); 1207 } 1208 1209 config_vars_free(resolv_conf); 1210 1211 dfui_form_free(f); 1212 dfui_response_free(r); 1213 } 1214 1215 static const char * 1216 yes_to_y(const char *value) 1217 { 1218 return(strcasecmp(value, "YES") == 0 ? "Y" : "N"); 1219 } 1220 1221 void 1222 fn_select_services(struct i_fn_args *a) 1223 { 1224 struct dfui_dataset *ds; 1225 struct dfui_form *f; 1226 struct dfui_response *r; 1227 1228 if (!config_vars_read(a, rc_conf, CONFIG_TYPE_SH, "%s%setc/rc.conf", 1229 a->os_root, a->cfg_root)) { 1230 inform(a->c, _("Couldn't read %s%setc/rc.conf."), 1231 a->os_root, a->cfg_root); 1232 a->result = 0; 1233 return; 1234 } 1235 1236 f = dfui_form_create( 1237 "select_services", 1238 _("Select Services"), 1239 _("Please select which services you would like " 1240 "started at boot time."), 1241 "", 1242 1243 "f", "syslogd", "syslogd", 1244 _("System Logging Daemon"), "", 1245 "p", "control", "checkbox", 1246 "f", "inetd", "inetd", 1247 _("Internet Super-Server"), "", 1248 "p", "control", "checkbox", 1249 "f", "named", "named", 1250 _("BIND Name Server"), "", 1251 "p", "control", "checkbox", 1252 "f", "ntpd", "ntpd", 1253 _("Network Time Protocol Daemon"), "", 1254 "p", "control", "checkbox", 1255 "f", "sshd", "sshd", 1256 _("Secure Shell Daemon"), "", 1257 "p", "control", "checkbox", 1258 1259 "a", "ok", _("Enable/Disable Services"), 1260 "", "", 1261 "a", "cancel", _("Return to Utilities Menu"), 1262 "", "", 1263 "p", "accelerator", "ESC", 1264 1265 NULL 1266 ); 1267 1268 ds = dfui_dataset_new(); 1269 dfui_dataset_celldata_add(ds, "syslogd", 1270 yes_to_y(config_var_get(rc_conf, "syslogd_enable"))); 1271 dfui_dataset_celldata_add(ds, "inetd", 1272 yes_to_y(config_var_get(rc_conf, "inetd_enable"))); 1273 dfui_dataset_celldata_add(ds, "named", 1274 yes_to_y(config_var_get(rc_conf, "named_enable"))); 1275 dfui_dataset_celldata_add(ds, "ntpd", 1276 yes_to_y(config_var_get(rc_conf, "ntpd_enable"))); 1277 dfui_dataset_celldata_add(ds, "sshd", 1278 yes_to_y(config_var_get(rc_conf, "sshd_enable"))); 1279 dfui_form_dataset_add(f, ds); 1280 1281 if (!dfui_be_present(a->c, f, &r)) 1282 abort_backend(); 1283 1284 if (strcmp(dfui_response_get_action_id(r), "cancel") == 0) { 1285 dfui_form_free(f); 1286 dfui_response_free(r); 1287 return; 1288 } 1289 1290 dfui_form_free(f); 1291 dfui_response_free(r); 1292 } 1293 1294 /*** NON-fn_ FUNCTIONS ***/ 1295 1296 /* 1297 * Uses ss->selected_{disk,slice} as the target system. 1298 * 1299 * XXX We now assume that the root mount has enough of the topology 1300 * to handle any configuration actions. 1301 */ 1302 int 1303 mount_target_system(struct i_fn_args *a) 1304 { 1305 FILE *crypttab, *fstab; 1306 struct commands *cmds; 1307 struct command *cmd; 1308 struct subpartition *a_subpart; 1309 struct subpartition *d_subpart; 1310 char name[256], device[256]; 1311 char *filename, line[256]; 1312 char *word; 1313 1314 /* 1315 * Mount subpartitions from this installation if they are 1316 * not already mounted. Tricky, as we need to honour the 1317 * installation's loader.conf and fstab. 1318 */ 1319 cmds = commands_new(); 1320 1321 /* 1322 * First, unmount anything already mounted on /mnt. 1323 */ 1324 unmount_all_under(a, cmds, "%smnt", a->os_root); 1325 1326 /* 1327 * Reset and clear out subpartitions so that system 1328 * can make a "dummy" subpart. 1329 */ 1330 subpartitions_free(storage_get_selected_slice(a->s)); 1331 1332 /* 1333 * Create a temporary dummy subpartition - that we 1334 * assume exists 1335 */ 1336 a_subpart = subpartition_new_ufs(storage_get_selected_slice(a->s), 1337 "/dummy", 0, 0, 0, 0, 0, 0); 1338 subpartition_new_ufs(storage_get_selected_slice(a->s), 1339 "swap", 0, 0, 0, 0, 0, 0); 1340 d_subpart = subpartition_new_ufs(storage_get_selected_slice(a->s), 1341 "/dummy", 0, 0, 0, 0, 0, 0); 1342 1343 /* 1344 * Mount the target's / and read its /etc/fstab. 1345 * 1346 * XXX NEEDS TO BE REWRITTEN XXX 1347 */ 1348 { 1349 command_add(cmds, "%s%s /dev/%s %sboot", 1350 a->os_root, cmd_name(a, "MOUNT"), 1351 subpartition_get_device_name(a_subpart), 1352 a->os_root); 1353 cmd = command_add(cmds, 1354 "%s%s -f %st2;" 1355 "%s%s \"^vfs\\.root\\.realroot=\" %sboot/loader.conf >%st2", 1356 a->os_root, cmd_name(a, "RM"), a->tmp, 1357 a->os_root, cmd_name(a, "GREP"), 1358 a->os_root, a->tmp); 1359 command_set_failure_mode(cmd, COMMAND_FAILURE_IGNORE); 1360 } 1361 if (!commands_execute(a, cmds)) { 1362 commands_free(cmds); 1363 return(0); 1364 } 1365 commands_free(cmds); 1366 cmds = commands_new(); 1367 1368 /* 1369 * XXX NEEDS TO BE REWRITTEN XXX 1370 */ 1371 { 1372 struct stat sb = { .st_size = 0 }; 1373 const char *fsname; 1374 const char *mountid; 1375 1376 switch (use_hammer) { 1377 case 1: 1378 fsname = "hammer"; 1379 mountid = "MOUNT_HAMMER"; 1380 break; 1381 case 2: 1382 fsname = "hammer2"; 1383 mountid = "MOUNT_HAMMER2"; 1384 break; 1385 case 0: 1386 default: 1387 fsname = "ufs"; 1388 mountid = "MOUNT"; 1389 break; 1390 } 1391 1392 stat("/tmp/t2", &sb); 1393 if (sb.st_size > 0) { 1394 command_add(cmds, "%s%s %sboot", 1395 a->os_root, cmd_name(a, "UMOUNT"), 1396 a->os_root); 1397 fn_get_passphrase(a); 1398 command_add(cmds, 1399 "%s%s -d /tmp/t1 luksOpen /dev/`%s%s \"^vfs\\.root\\.realroot=\" %st2 |" 1400 "%s%s -F%s: '{print $2;}' |" 1401 "%s%s -F: '{print $1;}'` %s", 1402 a->os_root, cmd_name(a, "CRYPTSETUP"), 1403 a->os_root, cmd_name(a, "GREP"), 1404 a->tmp, 1405 a->os_root, cmd_name(a, "AWK"), 1406 fsname, 1407 a->os_root, cmd_name(a, "AWK"), 1408 subpartition_get_mapper_name(d_subpart, -1)); 1409 command_add(cmds, 1410 "%s%s %s %s%s", 1411 a->os_root, 1412 cmd_name(a, mountid), 1413 subpartition_get_mapper_name(d_subpart, 1), 1414 a->os_root, a->cfg_root); 1415 } else { 1416 command_add(cmds, 1417 "%s%s /dev/`%s%s \"^vfs\\.root\\.mountfrom\" %sboot/loader.conf |" 1418 "%s%s -F%s: '{print $2;}' |" 1419 "%s%s 's/\"//'` %s%s", 1420 a->os_root, 1421 cmd_name(a, mountid), 1422 a->os_root, cmd_name(a, "GREP"), 1423 a->os_root, 1424 a->os_root, cmd_name(a, "AWK"), 1425 fsname, 1426 a->os_root, cmd_name(a, "SED"), 1427 a->os_root, a->cfg_root); 1428 command_add(cmds, "%s%s %sboot", 1429 a->os_root, cmd_name(a, "UMOUNT"), 1430 a->os_root); 1431 } 1432 } 1433 if (!commands_execute(a, cmds)) { 1434 commands_free(cmds); 1435 return(0); 1436 } 1437 commands_free(cmds); 1438 cmds = commands_new(); 1439 1440 /* 1441 * Get rid of the dummy subpartition. 1442 */ 1443 subpartitions_free(storage_get_selected_slice(a->s)); 1444 1445 /* 1446 * See if an /etc/crypttab exists. 1447 * 1448 * Scan and open the related mappings (currently not used since 1449 * we removed the additional mounts from the fstab scan, but we 1450 * might put those back in at a future date so leave this in for 1451 * now). 1452 */ 1453 asprintf(&filename, "%s%s/etc/crypttab", a->os_root, a->cfg_root); 1454 crypttab = fopen(filename, "r"); 1455 free(filename); 1456 if (crypttab != NULL) { 1457 while (fgets(line, 256, crypttab) != NULL) { 1458 /* 1459 * Parse the crypttab line. 1460 */ 1461 if (first_non_space_char_is(line, '#')) 1462 continue; 1463 if ((word = strtok(line, " \t")) == NULL) 1464 continue; 1465 strlcpy(name, word, 256); 1466 1467 /* don't mount encrypted swap */ 1468 if (strcmp(name, "swap") == 0) 1469 continue; 1470 /* encrypted root already mounted */ 1471 if (strcmp(name, subpartition_get_mapper_name(d_subpart, -1)) == 0) 1472 continue; 1473 1474 if ((word = strtok(NULL, " \t")) == NULL) 1475 continue; 1476 strlcpy(device, word, 256); 1477 1478 command_add(cmds, 1479 "%s%s -d /tmp/t1 luksOpen %s %s", 1480 a->os_root, cmd_name(a, "CRYPTSETUP"), 1481 device, name); 1482 1483 continue; 1484 } 1485 fclose(crypttab); 1486 } 1487 if (!commands_execute(a, cmds)) { 1488 commands_free(cmds); 1489 return(0); 1490 } 1491 commands_free(cmds); 1492 1493 /* 1494 * (current we do not mount the other partitions, everything needed 1495 * for system configuration should be on the already-mounted root). 1496 */ 1497 asprintf(&filename, "%s%s/etc/fstab", a->os_root, a->cfg_root); 1498 fstab = fopen(filename, "r"); 1499 free(filename); 1500 if (fstab == NULL) { 1501 inform(a->c, _("Filesystem table on installed system could not be read.")); 1502 cmds = commands_new(); 1503 command_add(cmds, "%s%s %s%s", 1504 a->os_root, cmd_name(a, "UMOUNT"), 1505 a->os_root, a->cfg_root); 1506 if (!commands_execute(a, cmds)) { 1507 inform(a->c, _("Warning: Installed system was not properly unmounted.")); 1508 } 1509 commands_free(cmds); 1510 return(0); 1511 } 1512 fclose(fstab); 1513 1514 return 1; 1515 } 1516