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