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