install.c revision 38703
1232922Stheraven/* 2232922Stheraven * The new sysinstall program. 3232922Stheraven * 4232922Stheraven * This is probably the last program in the `sysinstall' line - the next 5232922Stheraven * generation being essentially a complete rewrite. 6232922Stheraven * 7232922Stheraven * $Id: install.c,v 1.209 1998/07/18 09:42:00 jkh Exp $ 8232922Stheraven * 9232922Stheraven * Copyright (c) 1995 10232922Stheraven * Jordan Hubbard. All rights reserved. 11232922Stheraven * 12232922Stheraven * Redistribution and use in source and binary forms, with or without 13232922Stheraven * modification, are permitted provided that the following conditions 14232922Stheraven * are met: 15232922Stheraven * 1. Redistributions of source code must retain the above copyright 16232922Stheraven * notice, this list of conditions and the following disclaimer, 17232922Stheraven * verbatim and that no modifications are made prior to this 18232922Stheraven * point in the file. 19232922Stheraven * 2. Redistributions in binary form must reproduce the above copyright 20232922Stheraven * notice, this list of conditions and the following disclaimer in the 21232922Stheraven * documentation and/or other materials provided with the distribution. 22232922Stheraven * 23232922Stheraven * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 24232922Stheraven * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25232922Stheraven * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26232922Stheraven * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 27227825Stheraven * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28227825Stheraven * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29227825Stheraven * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 30227825Stheraven * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31227825Stheraven * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32233233Stheraven * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33233233Stheraven * SUCH DAMAGE. 34233233Stheraven * 35233233Stheraven */ 36227825Stheraven 37233233Stheraven#include "sysinstall.h" 38233233Stheraven#include "uc_main.h" 39233233Stheraven#include <ctype.h> 40233233Stheraven#include <sys/disklabel.h> 41233233Stheraven#include <sys/errno.h> 42233233Stheraven#include <sys/ioctl.h> 43233233Stheraven#include <sys/fcntl.h> 44233233Stheraven#include <sys/wait.h> 45233233Stheraven#include <sys/param.h> 46233233Stheraven#define MSDOSFS 47233233Stheraven#include <sys/mount.h> 48233233Stheraven#include <ufs/ufs/ufsmount.h> 49233233Stheraven#include <msdosfs/msdosfsmount.h> 50233233Stheraven#undef MSDOSFS 51233233Stheraven#include <sys/stat.h> 52233233Stheraven#include <unistd.h> 53233233Stheraven 54233233Stheravenstatic void create_termcap(void); 55233233Stheravenstatic void fixit_common(void); 56233233Stheraven#ifdef SAVE_USERCONFIG 57233233Stheravenstatic void save_userconfig_to_kernel(char *); 58233233Stheraven#endif 59233233Stheraven 60233233Stheraven#define TERMCAP_FILE "/usr/share/misc/termcap" 61233233Stheraven 62233233Stheravenstatic void installConfigure(void); 63233233Stheraven 64233233StheravenBoolean 65233233StheravencheckLabels(Boolean whinge, Chunk **rdev, Chunk **sdev, Chunk **udev, Chunk **vdev) 66233233Stheraven{ 67233233Stheraven Device **devs; 68233233Stheraven Boolean status; 69233233Stheraven Disk *disk; 70233233Stheraven Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev; 71233233Stheraven int i; 72233233Stheraven 73245302Stheraven /* Don't allow whinging if noWarn is set */ 74245302Stheraven if (variable_get(VAR_NO_WARN)) 75245302Stheraven whinge = FALSE; 76245302Stheraven 77245302Stheraven status = TRUE; 78245302Stheraven *rdev = *sdev = *udev = *vdev = rootdev = swapdev = usrdev = vardev = NULL; 79245302Stheraven 80245302Stheraven /* We don't need to worry about root/usr/swap if we're already multiuser */ 81233233Stheraven if (!RunningAsInit) 82233233Stheraven return status; 83233233Stheraven 84233233Stheraven devs = deviceFind(NULL, DEVICE_TYPE_DISK); 85233233Stheraven /* First verify that we have a root device */ 86233233Stheraven for (i = 0; devs[i]; i++) { 87233233Stheraven if (!devs[i]->enabled) 88233233Stheraven continue; 89233233Stheraven disk = (Disk *)devs[i]->private; 90233233Stheraven msgDebug("Scanning disk %s for root filesystem\n", disk->name); 91233233Stheraven if (!disk->chunks) 92233233Stheraven msgFatal("No chunk list found for %s!", disk->name); 93233233Stheraven for (c1 = disk->chunks->part; c1; c1 = c1->next) { 94233233Stheraven if (c1->type == freebsd) { 95233233Stheraven for (c2 = c1->part; c2; c2 = c2->next) { 96233233Stheraven if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) { 97233233Stheraven if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/")) { 98233233Stheraven if (rootdev) { 99233233Stheraven if (whinge) 100233233Stheraven msgConfirm("WARNING: You have more than one root device set?!\n" 101233233Stheraven "Using the first one found."); 102233233Stheraven continue; 103233233Stheraven } 104233233Stheraven else { 105233233Stheraven rootdev = c2; 106233233Stheraven if (isDebug()) 107233233Stheraven msgDebug("Found rootdev at %s!\n", rootdev->name); 108233233Stheraven } 109233233Stheraven } 110233233Stheraven else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/usr")) { 111233233Stheraven if (usrdev) { 112233233Stheraven if (whinge) 113227825Stheraven msgConfirm("WARNING: You have more than one /usr filesystem.\n" 114227825Stheraven "Using the first one found."); 115227825Stheraven continue; 116227825Stheraven } 117227825Stheraven else { 118227825Stheraven usrdev = c2; 119227825Stheraven if (isDebug()) 120227825Stheraven msgDebug("Found usrdev at %s!\n", usrdev->name); 121227825Stheraven } 122227825Stheraven } 123227825Stheraven else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/var")) { 124227825Stheraven if (vardev) { 125227825Stheraven if (whinge) 126227825Stheraven msgConfirm("WARNING: You have more than one /var filesystem.\n" 127227825Stheraven "Using the first one found."); 128227825Stheraven continue; 129227825Stheraven } 130227825Stheraven else { 131227825Stheraven vardev = c2; 132233233Stheraven if (isDebug()) 133227825Stheraven msgDebug("Found vardev at %s!\n", vardev->name); 134227825Stheraven } 135227825Stheraven } 136227825Stheraven } 137227825Stheraven } 138227825Stheraven } 139227825Stheraven } 140227825Stheraven } 141227825Stheraven 142227825Stheraven /* Now check for swap devices */ 143227825Stheraven for (i = 0; devs[i]; i++) { 144227825Stheraven if (!devs[i]->enabled) 145227825Stheraven continue; 146227825Stheraven disk = (Disk *)devs[i]->private; 147227825Stheraven msgDebug("Scanning disk %s for swap partitions\n", disk->name); 148227825Stheraven if (!disk->chunks) 149227825Stheraven msgFatal("No chunk list found for %s!", disk->name); 150227825Stheraven for (c1 = disk->chunks->part; c1; c1 = c1->next) { 151233233Stheraven if (c1->type == freebsd) { 152233233Stheraven for (c2 = c1->part; c2; c2 = c2->next) { 153233233Stheraven if (c2->type == part && c2->subtype == FS_SWAP && !swapdev) { 154233233Stheraven swapdev = c2; 155233233Stheraven if (isDebug()) 156233233Stheraven msgDebug("Found swapdev at %s!\n", swapdev->name); 157227825Stheraven break; 158227825Stheraven } 159227825Stheraven } 160227825Stheraven } 161227825Stheraven } 162227825Stheraven } 163227825Stheraven 164227825Stheraven /* Copy our values over */ 165227825Stheraven *rdev = rootdev; 166227825Stheraven *sdev = swapdev; 167233233Stheraven *udev = usrdev; 168233233Stheraven *vdev = vardev; 169233233Stheraven 170227825Stheraven if (!rootdev && whinge) { 171227825Stheraven msgConfirm("No root device found - you must label a partition as /\n" 172227825Stheraven "in the label editor."); 173227825Stheraven status = FALSE; 174227825Stheraven } 175227825Stheraven if (!swapdev && whinge) { 176227825Stheraven msgConfirm("No swap devices found - you must create at least one\n" 177227825Stheraven "swap partition."); 178227825Stheraven status = FALSE; 179227825Stheraven } 180227825Stheraven if (!usrdev && whinge && !variable_get(VAR_NO_USR)) { 181227825Stheraven msgConfirm("WARNING: No /usr filesystem found. This is not technically\n" 182227825Stheraven "an error if your root filesystem is big enough (or you later\n" 183227825Stheraven "intend to mount your /usr filesystem over NFS), but it may otherwise\n" 184227825Stheraven "cause you trouble if you're not exactly sure what you are doing!"); 185227825Stheraven } 186227825Stheraven if (!vardev && whinge && variable_cmp(SYSTEM_STATE, "upgrade")) { 187227825Stheraven msgConfirm("WARNING: No /var filesystem found. This is not technically\n" 188227825Stheraven "an error if your root filesystem is big enough (or you later\n" 189227825Stheraven "intend to link /var to someplace else), but it may otherwise\n" 190227825Stheraven "cause your root filesystem to fill up if you receive lots of mail\n" 191227825Stheraven "or edit large temporary files."); 192227825Stheraven } 193227825Stheraven return status; 194227825Stheraven} 195227825Stheraven 196227825Stheravenstatic int 197227825StheraveninstallInitial(void) 198227825Stheraven{ 199227825Stheraven static Boolean alreadyDone = FALSE; 200227825Stheraven 201227825Stheraven if (alreadyDone) 202227825Stheraven return DITEM_SUCCESS; 203227825Stheraven 204227825Stheraven if (!variable_get(DISK_LABELLED)) { 205227825Stheraven msgConfirm("You need to assign disk labels before you can proceed with\n" 206227825Stheraven "the installation."); 207227825Stheraven return DITEM_FAILURE; 208227825Stheraven } 209227825Stheraven /* If it's labelled, assume it's also partitioned */ 210227825Stheraven if (!variable_get(DISK_PARTITIONED)) 211227825Stheraven variable_set2(DISK_PARTITIONED, "yes"); 212227825Stheraven 213227825Stheraven /* If we refuse to proceed, bail. */ 214227825Stheraven dialog_clear_norefresh(); 215227825Stheraven if (!variable_get(VAR_NO_WARN)) 216227825Stheraven if (msgYesNo( 217227825Stheraven "Last Chance! Are you SURE you want continue the installation?\n\n" 218227825Stheraven "If you're running this on a disk with data you wish to save\n" 219227825Stheraven "then WE STRONGLY ENCOURAGE YOU TO MAKE PROPER BACKUPS before\n" 220227825Stheraven "proceeding!\n\n" 221227825Stheraven "We can take no responsibility for lost disk contents!") != 0) 222227825Stheraven return DITEM_FAILURE | DITEM_RESTORE; 223227825Stheraven 224227825Stheraven if (DITEM_STATUS(diskLabelCommit(NULL)) != DITEM_SUCCESS) { 225227825Stheraven msgConfirm("Couldn't make filesystems properly. Aborting."); 226227825Stheraven return DITEM_FAILURE; 227227825Stheraven } 228227825Stheraven 229227825Stheraven if (!copySelf()) { 230227825Stheraven msgConfirm("installInitial: Couldn't clone the boot floppy onto the\n" 231227825Stheraven "root file system. Aborting!"); 232227825Stheraven return DITEM_FAILURE; 233227825Stheraven } 234227825Stheraven 235227825Stheraven if (chroot("/mnt") == -1) { 236227825Stheraven msgConfirm("installInitial: Unable to chroot to %s - this is bad!", 237227825Stheraven "/mnt"); 238227825Stheraven return DITEM_FAILURE; 239227825Stheraven } 240227825Stheraven 241227825Stheraven chdir("/"); 242227825Stheraven variable_set2(RUNNING_ON_ROOT, "yes"); 243227825Stheraven configResolv(); 244227825Stheraven 245227825Stheraven /* stick a helpful shell over on the 4th VTY */ 246227825Stheraven systemCreateHoloshell(); 247227825Stheraven 248227825Stheraven alreadyDone = TRUE; 249227825Stheraven return DITEM_SUCCESS; 250233233Stheraven} 251233233Stheraven 252233233Stheravenint 253227825StheraveninstallFixitHoloShell(dialogMenuItem *self) 254227825Stheraven{ 255227825Stheraven systemCreateHoloshell(); 256227825Stheraven return DITEM_SUCCESS; 257227825Stheraven} 258227825Stheraven 259227825Stheravenint 260227825StheraveninstallFixitCDROM(dialogMenuItem *self) 261227825Stheraven{ 262227825Stheraven struct stat sb; 263227825Stheraven 264227825Stheraven if (!RunningAsInit) 265227825Stheraven return DITEM_SUCCESS; 266227825Stheraven 267227825Stheraven variable_set2(SYSTEM_STATE, "fixit"); 268227825Stheraven (void)unlink("/mnt2"); 269227825Stheraven (void)rmdir("/mnt2"); 270227825Stheraven 271227825Stheraven while (1) { 272227825Stheraven msgConfirm("Please insert the second FreeBSD CDROM and press return"); 273227825Stheraven if (DITEM_STATUS(mediaSetCDROM(NULL)) != DITEM_SUCCESS || !mediaDevice || !mediaDevice->init(mediaDevice)) { 274227825Stheraven /* If we can't initialize it, it's probably not a FreeBSD CDROM so punt on it */ 275227825Stheraven if (mediaDevice) { 276227825Stheraven mediaDevice->shutdown(mediaDevice); 277227825Stheraven mediaDevice = NULL; 278227825Stheraven } 279227825Stheraven if (msgYesNo("Unable to mount the CDROM - do you want to try again?") != 0) 280227825Stheraven return DITEM_FAILURE; 281227825Stheraven } 282227825Stheraven else 283227825Stheraven break; 284227825Stheraven } 285227825Stheraven 286227825Stheraven /* Since the fixit code expects everything to be in /mnt2, and the CDROM mounting stuff /dist, do 287233233Stheraven * a little kludge dance here.. 288233233Stheraven */ 289233233Stheraven if (symlink("/dist", "/mnt2")) { 290227825Stheraven msgConfirm("Unable to symlink /mnt2 to the CDROM mount point. Please report this\n" 291227825Stheraven "unexpected failure to freebsd-bugs@FreeBSD.org."); 292227825Stheraven return DITEM_FAILURE; 293227825Stheraven } 294227825Stheraven 295227825Stheraven /* 296227825Stheraven * If /tmp points to /mnt2/tmp from a previous fixit floppy session, it's 297227825Stheraven * not very good for us if we point it to the CDROM now. Rather make it 298245302Stheraven * a directory in the root MFS then. Experienced admins will still be 299227825Stheraven * able to mount their disk's /tmp over this if they need. 300227825Stheraven */ 301227825Stheraven if (lstat("/tmp", &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFLNK) 302227825Stheraven (void)unlink("/tmp"); 303227825Stheraven Mkdir("/tmp"); 304227825Stheraven 305227825Stheraven /* 306227825Stheraven * Since setuid binaries ignore LD_LIBRARY_PATH, we indeed need the 307227825Stheraven * ld.so.hints file. Fortunately, it's fairly small (~ 3 KB). 308227825Stheraven */ 309227825Stheraven if (!file_readable("/var/run/ld.so.hints")) { 310227825Stheraven Mkdir("/var/run"); 311227825Stheraven if (vsystem("/mnt2/sbin/ldconfig -s /mnt2/usr/lib")) { 312227825Stheraven msgConfirm("Warning: ldconfig could not create the ld.so hints file.\n" 313227825Stheraven "Dynamic executables from the CDROM likely won't work."); 314 } 315 } 316 317 /* Yet another iggly hardcoded pathname. */ 318 if (!file_readable("/usr/libexec/ld.so")) { 319 Mkdir("/usr/libexec"); 320 if (symlink("/mnt2/usr/libexec/ld.so", "/usr/libexec/ld.so")) { 321 msgConfirm("Warning: could not create the symlink for ld.so.\n" 322 "Dynamic executables from the CDROM likely won't work."); 323 } 324 } 325 326 fixit_common(); 327 328 mediaDevice->shutdown(mediaDevice); 329 msgConfirm("Please remove the FreeBSD CDROM now."); 330 return DITEM_SUCCESS; 331} 332 333int 334installFixitFloppy(dialogMenuItem *self) 335{ 336 struct ufs_args args; 337 338 if (!RunningAsInit) 339 return DITEM_SUCCESS; 340 341 variable_set2(SYSTEM_STATE, "fixit"); 342 Mkdir("/mnt2"); 343 344 /* Try to open the floppy drive */ 345 if (DITEM_STATUS(mediaSetFloppy(NULL)) == DITEM_FAILURE) { 346 msgConfirm("Unable to set media device to floppy."); 347 mediaClose(); 348 return DITEM_FAILURE; 349 } 350 351 memset(&args, 0, sizeof(args)); 352 args.fspec = mediaDevice->devname; 353 354 while (1) { 355 msgConfirm("Please insert a writable fixit floppy and press return"); 356 if (mount("ufs", "/mnt2", 0, (caddr_t)&args) != -1) 357 break; 358 msgConfirm("An attempt to mount the fixit floppy failed, maybe the filesystem\n" 359 "is unclean. Trying a forcible mount as a last resort..."); 360 if (mount("ufs", "/mnt2", MNT_FORCE, (caddr_t)&args) != -1) 361 break; 362 if (msgYesNo("Unable to mount the fixit floppy - do you want to try again?") != 0) 363 return DITEM_FAILURE; 364 } 365 366 if (!directory_exists("/tmp")) 367 (void)symlink("/mnt2/tmp", "/tmp"); 368 369 fixit_common(); 370 371 unmount("/mnt2", MNT_FORCE); 372 msgConfirm("Please remove the fixit floppy now."); 373 return DITEM_SUCCESS; 374} 375 376/* 377 * The common code for both fixit variants. 378 */ 379static void 380fixit_common(void) 381{ 382 pid_t child; 383 int waitstatus; 384 385 if (!directory_exists("/var/tmp/vi.recover")) { 386 if (DITEM_STATUS(Mkdir("/var/tmp/vi.recover")) != DITEM_SUCCESS) { 387 msgConfirm("Warning: Was unable to create a /var/tmp/vi.recover directory.\n" 388 "vi will kvetch and moan about it as a result but should still\n" 389 "be essentially usable."); 390 } 391 } 392 if (!directory_exists("/bin")) 393 (void)Mkdir("/bin"); 394 (void)symlink("/stand/sh", "/bin/sh"); 395 /* Link the /etc/ files */ 396 if (DITEM_STATUS(Mkdir("/etc")) != DITEM_SUCCESS) 397 msgConfirm("Unable to create an /etc directory! Things are weird on this floppy.."); 398 else if ((symlink("/mnt2/etc/spwd.db", "/etc/spwd.db") == -1 && errno != EEXIST) || 399 (symlink("/mnt2/etc/protocols", "/etc/protocols") == -1 && errno != EEXIST) || 400 (symlink("/mnt2/etc/services", "/etc/services") == -1 && errno != EEXIST)) 401 msgConfirm("Couldn't symlink the /etc/ files! I'm not sure I like this.."); 402 if (!file_readable(TERMCAP_FILE)) 403 create_termcap(); 404 if (!(child = fork())) { 405 int i, fd; 406 struct termios foo; 407 extern int login_tty(int); 408 409 ioctl(0, TIOCNOTTY, NULL); 410 for (i = getdtablesize(); i >= 0; --i) 411 close(i); 412 fd = open("/dev/ttyv3", O_RDWR); 413 ioctl(0, TIOCSCTTY, &fd); 414 dup2(0, 1); 415 dup2(0, 2); 416 DebugFD = 2; 417 if (login_tty(fd) == -1) 418 msgDebug("fixit: I can't set the controlling terminal.\n"); 419 420 signal(SIGTTOU, SIG_IGN); 421 if (tcgetattr(0, &foo) != -1) { 422 foo.c_cc[VERASE] = '\010'; 423 if (tcsetattr(0, TCSANOW, &foo) == -1) 424 msgDebug("fixit shell: Unable to set erase character.\n"); 425 } 426 else 427 msgDebug("fixit shell: Unable to get terminal attributes!\n"); 428 setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/stand:" 429 "/mnt2/stand:/mnt2/bin:/mnt2/sbin:/mnt2/usr/bin:/mnt2/usr/sbin", 1); 430 /* use the .profile from the fixit medium */ 431 setenv("HOME", "/mnt2", 1); 432 chdir("/mnt2"); 433 execlp("sh", "-sh", 0); 434 msgDebug("fixit shell: Failed to execute shell!\n"); 435 _exit(1);; 436 } 437 else { 438 msgNotify("Waiting for fixit shell to exit. Go to VTY4 now by\n" 439 "typing ALT-F4. When you are done, type ``exit'' to exit\n" 440 "the fixit shell and be returned here."); 441 (void)waitpid(child, &waitstatus, 0); 442 } 443 dialog_clear(); 444} 445 446 447int 448installExpress(dialogMenuItem *self) 449{ 450 int i; 451 452 variable_set2(SYSTEM_STATE, "express"); 453 if (DITEM_STATUS((i = diskPartitionEditor(self))) == DITEM_FAILURE) 454 return i; 455 456 if (DITEM_STATUS((i = diskLabelEditor(self))) == DITEM_FAILURE) 457 return i; 458 459 dialog_clear_norefresh(); 460 if (DITEM_STATUS((i = installCommit(self))) == DITEM_SUCCESS) { 461 i |= DITEM_LEAVE_MENU; 462 /* Give user the option of one last configuration spree */ 463 installConfigure(); 464 } 465 return i | DITEM_RESTORE; 466} 467 468/* Novice mode installation */ 469int 470installNovice(dialogMenuItem *self) 471{ 472 int i, tries = 0; 473 Device **devs; 474 475 variable_set2(SYSTEM_STATE, "novice"); 476 dialog_clear_norefresh(); 477 msgConfirm("In the next menu, you will need to set up a DOS-style (\"fdisk\") partitioning\n" 478 "scheme for your hard disk. If you simply wish to devote all disk space\n" 479 "to FreeBSD (overwriting anything else that might be on the disk(s) selected)\n" 480 "then use the (A)ll command to select the default partitioning scheme followed\n" 481 "by a (Q)uit. If you wish to allocate only free space to FreeBSD, move to a\n" 482 "partition marked \"unused\" and use the (C)reate command."); 483 484nodisks: 485 if (DITEM_STATUS(diskPartitionEditor(self)) == DITEM_FAILURE) 486 return DITEM_FAILURE; 487 488 if (diskGetSelectCount(&devs) <= 0 && tries < 3) { 489 msgConfirm("You need to select some disks to operate on! Be sure to use SPACE\n" 490 "instead of RETURN in the disk selection menu when selecting a disk."); 491 ++tries; 492 goto nodisks; 493 } 494 495 dialog_clear_norefresh(); 496 msgConfirm("Next, you need to create BSD partitions inside of the fdisk partition(s)\n" 497 "just created. If you have a reasonable amount of disk space (200MB or more)\n" 498 "and don't have any special requirements, simply use the (A)uto command to\n" 499 "allocate space automatically. If you have more specific needs or just don't\n" 500 "care for the layout chosen by (A)uto, press F1 for more information on\n" 501 "manual layout."); 502 503 if (DITEM_STATUS(diskLabelEditor(self)) == DITEM_FAILURE) 504 return DITEM_FAILURE; 505 506 dialog_clear_norefresh(); 507 if (DITEM_STATUS((i = installCommit(self))) == DITEM_FAILURE) { 508 dialog_clear_norefresh(); 509 msgConfirm("Installation completed with some errors. You may wish to\n" 510 "scroll through the debugging messages on VTY1 with the\n" 511 "scroll-lock feature. You can also chose \"No\" at the next\n" 512 "prompt and go back into the installation menus to try and retry\n" 513 "whichever operations have failed."); 514 return i | DITEM_RESTORE; 515 516 } 517 else { 518 dialog_clear_norefresh(); 519 msgConfirm("Congratulations! You now have FreeBSD installed on your system.\n\n" 520 "We will now move on to the final configuration questions.\n" 521 "For any option you do not wish to configure, simply select\n" 522 "No.\n\n" 523 "If you wish to re-enter this utility after the system is up, you\n" 524 "may do so by typing: /stand/sysinstall."); 525 } 526 if (mediaDevice->type != DEVICE_TYPE_FTP && mediaDevice->type != DEVICE_TYPE_NFS) { 527 if (!msgYesNo("Would you like to configure any Ethernet or SLIP/PPP network devices?")) { 528 Device *tmp; 529 530 dialog_clear_norefresh(); 531 tmp = tcpDeviceSelect(); 532 dialog_clear_norefresh(); 533 if (tmp && !msgYesNo("Would you like to bring the %s interface up right now?", tmp->name)) 534 if (!tmp->init(tmp)) 535 msgConfirm("Initialization of %s device failed.", tmp->name); 536 } 537 } 538 539 dialog_clear_norefresh(); 540 if (!msgYesNo("Will this machine be an IP gateway (e.g. will it forward packets\n" 541 "between interfaces)?")) 542 variable_set2("gateway_enable", "YES"); 543 544 dialog_clear_norefresh(); 545 if (!msgYesNo("Do you want to allow anonymous FTP connections to this machine?")) 546 configAnonFTP(self); 547 548 dialog_clear_norefresh(); 549 if (!msgYesNo("Do you want to configure this machine as an NFS server?")) 550 configNFSServer(self); 551 552 dialog_clear_norefresh(); 553 if (!msgYesNo("Do you want to configure this machine as an NFS client?")) 554 variable_set2("nfs_client_enable", "YES"); 555 556 dialog_clear_norefresh(); 557 if (!msgYesNo("Would you like to customize your system console settings?")) { 558 WINDOW *w = savescr(); 559 560 dmenuOpenSimple(&MenuSyscons, FALSE); 561 restorescr(w); 562 } 563 564 dialog_clear_norefresh(); 565 if (!msgYesNo("Would you like to set this machine's time zone now?")) { 566 WINDOW *w = savescr(); 567 568 dialog_clear(); 569 systemExecute("tzsetup"); 570 restorescr(w); 571 } 572 573 dialog_clear_norefresh(); 574 if (!msgYesNo("Does this system have a mouse attached to it?")) { 575 WINDOW *w = savescr(); 576 577 dmenuOpenSimple(&MenuMouse, FALSE); 578 restorescr(w); 579 } 580 581 /* Now would be a good time to checkpoint the configuration data */ 582 configRC_conf("/etc/rc.conf"); 583 sync(); 584 585 if (directory_exists("/usr/X11R6")) { 586 dialog_clear_norefresh(); 587 if (!msgYesNo("Would you like to configure your X server at this time?")) 588 configXEnvironment(self); 589 } 590 591 dialog_clear_norefresh(); 592 if (!msgYesNo("The FreeBSD package collection is a collection of hundreds of ready-to-run\n" 593 "applications, from text editors to games to WEB servers and more. Would you\n" 594 "like to browse the collection now?")) 595 configPackages(self); 596 597 dialog_clear_norefresh(); 598 if (!msgYesNo("Would you like to add any initial user accounts to the system?\n" 599 "Adding at least one account for yourself at this stage is suggested\n" 600 "since working as the \"root\" user is dangerous (it is easy to do\n" 601 "things which adversely affect the entire system).")) 602 configUsers(self); 603 604 dialog_clear_norefresh(); 605 msgConfirm("Now you must set the system manager's password.\n" 606 "This is the password you'll use to log in as \"root\"."); 607 { 608 WINDOW *w = savescr(); 609 610 if (!systemExecute("passwd root")) 611 variable_set2("root_password", "YES"); 612 restorescr(w); 613 } 614 615 dialog_clear_norefresh(); 616 if (!msgYesNo("Would you like to register your FreeBSD system at this time?\n\n" 617 "PLEASE, take just 5 minutes to do this. If we're ever to get any\n" 618 "significant base of commercial software for FreeBSD, we need to\n" 619 "be able to provide more information about the size of our user community.\n" 620 "This is where your registration can really help us, and you can also\n" 621 "sign up for the new FreeBSD newsletter (its free!) at the same time.\n")) 622 configRegister(NULL); 623 else { 624 dialog_clear_norefresh(); 625 msgConfirm("OK, but if you should change your mind then you always can register\n" 626 "later by typing ``/stand/sysinstall register'' or by simply visiting our\n" 627 "web site at http://www.freebsd.org/register.html"); 628 629 } 630 /* XXX Put whatever other nice configuration questions you'd like to ask the user here XXX */ 631 632 /* Give user the option of one last configuration spree */ 633 dialog_clear_norefresh(); 634 installConfigure(); 635 636 return DITEM_LEAVE_MENU | DITEM_RESTORE; 637} 638 639/* The version of commit we call from the Install Custom menu */ 640int 641installCustomCommit(dialogMenuItem *self) 642{ 643 int i; 644 645 dialog_clear_norefresh(); 646 i = installCommit(self); 647 if (DITEM_STATUS(i) == DITEM_SUCCESS) { 648 /* Give user the option of one last configuration spree */ 649 installConfigure(); 650 return i; 651 } 652 else 653 msgConfirm("The commit operation completed with errors. Not\n" 654 "updating /etc files."); 655 return i; 656} 657 658/* 659 * What happens when we finally decide to going ahead with the installation. 660 * 661 * This is broken into multiple stages so that the user can do a full 662 * installation but come back here again to load more distributions, 663 * perhaps from a different media type. This would allow, for 664 * example, the user to load the majority of the system from CDROM and 665 * then use ftp to load just the DES dist. 666 */ 667int 668installCommit(dialogMenuItem *self) 669{ 670 int i; 671 char *str; 672 Boolean need_bin; 673 674 if (!Dists) 675 distConfig(NULL); 676 677 if (!Dists) 678 if (!dmenuOpenSimple(&MenuDistributions, FALSE) && !Dists) 679 return DITEM_FAILURE | DITEM_RESTORE; 680 681 if (!mediaVerify()) 682 return DITEM_FAILURE | DITEM_RESTORE; 683 684 str = variable_get(SYSTEM_STATE); 685 if (isDebug()) 686 msgDebug("installCommit: System state is `%s'\n", str); 687 688 if (RunningAsInit) { 689 /* Do things we wouldn't do to a multi-user system */ 690 if (DITEM_STATUS((i = installInitial())) == DITEM_FAILURE) 691 return i; 692 if (DITEM_STATUS((i = configFstab())) == DITEM_FAILURE) 693 return i; 694 } 695 696try_media: 697 if (!mediaDevice->init(mediaDevice)) { 698 if (!msgYesNo("Unable to initialize selected media. Would you like to\n" 699 "adjust your media configuration and try again?")) { 700 mediaDevice = NULL; 701 if (!mediaVerify()) 702 return DITEM_FAILURE | DITEM_RESTORE; 703 else 704 goto try_media; 705 } 706 else 707 return DITEM_FAILURE | DITEM_RESTORE; 708 } 709 710 need_bin = Dists & DIST_BIN; 711 i = distExtractAll(self); 712 if (DITEM_STATUS(i) == DITEM_SUCCESS) { 713 if (need_bin && !(Dists & DIST_BIN)) 714 i = installFixup(self); 715 } 716 /* When running as init, *now* it's safe to grab the rc.foo vars */ 717 installEnvironment(); 718 719 variable_set2(SYSTEM_STATE, DITEM_STATUS(i) == DITEM_FAILURE ? "error-install" : "full-install"); 720 721 return i | DITEM_RESTORE; 722} 723 724static void 725installConfigure(void) 726{ 727 /* Final menu of last resort */ 728 dialog_clear_norefresh(); 729 if (!msgYesNo("Visit the general configuration menu for a chance to set\n" 730 "any last options?")) { 731 WINDOW *w = savescr(); 732 733 dmenuOpenSimple(&MenuConfigure, FALSE); 734 restorescr(w); 735 } 736 configRC_conf("/etc/rc.conf"); 737 sync(); 738} 739 740int 741installFixup(dialogMenuItem *self) 742{ 743 Device **devs; 744 int i; 745 746 if (!file_readable("/kernel")) { 747 if (file_readable("/kernel.GENERIC")) { 748#ifdef SAVE_USERCONFIG 749 /* Snapshot any boot -c changes back to the GENERIC kernel */ 750 if (!variable_cmp(VAR_RELNAME, RELEASE_NAME)) 751 save_userconfig_to_kernel("/kernel.GENERIC"); 752#endif 753 if (vsystem("cp -p /kernel.GENERIC /kernel")) { 754 msgConfirm("Unable to link /kernel into place!"); 755 return DITEM_FAILURE; 756 } 757 } 758 else { 759 msgConfirm("Can't find a kernel image to link to on the root file system!\n" 760 "You're going to have a hard time getting this system to\n" 761 "boot from the hard disk, I'm afraid!"); 762 return DITEM_FAILURE; 763 } 764 } 765 766 /* Resurrect /dev after bin distribution screws it up */ 767 if (RunningAsInit) { 768 msgNotify("Remaking all devices.. Please wait!"); 769 if (vsystem("cd /dev; sh MAKEDEV all")) { 770 msgConfirm("MAKEDEV returned non-zero status"); 771 return DITEM_FAILURE; 772 } 773 774 msgNotify("Resurrecting /dev entries for slices.."); 775 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 776 if (!devs) 777 msgFatal("Couldn't get a disk device list!"); 778 779 /* Resurrect the slices that the former clobbered */ 780 for (i = 0; devs[i]; i++) { 781 Disk *disk = (Disk *)devs[i]->private; 782 Chunk *c1; 783 784 if (!devs[i]->enabled) 785 continue; 786 if (!disk->chunks) 787 msgFatal("No chunk list found for %s!", disk->name); 788 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 789 if (c1->type == freebsd) { 790 msgNotify("Making slice entries for %s", c1->name); 791 if (vsystem("cd /dev; sh MAKEDEV %sh", c1->name)) { 792 msgConfirm("Unable to make slice entries for %s!", c1->name); 793 return DITEM_FAILURE; 794 } 795 } 796 } 797 } 798 /* XXX Do all the last ugly work-arounds here which we'll try and excise someday right?? XXX */ 799 800 msgNotify("Fixing permissions.."); 801 /* BOGON #1: XFree86 extracting /usr/X11R6 with root-only perms */ 802 if (directory_exists("/usr/X11R6")) { 803 vsystem("chmod -R a+r /usr/X11R6"); 804 vsystem("find /usr/X11R6 -type d | xargs chmod a+x"); 805 } 806 /* BOGON #2: We leave /etc in a bad state */ 807 chmod("/etc", 0755); 808 809 /* BOGON #3: No /var/db/mountdtab complains */ 810 Mkdir("/var/db"); 811 creat("/var/db/mountdtab", 0644); 812 813 /* BOGON #4: /compat created by default in root fs */ 814 Mkdir("/usr/compat"); 815 vsystem("ln -s /usr/compat /compat"); 816 817 /* BOGON #5: aliases database not build for bin */ 818 vsystem("newaliases"); 819 820 /* BOGON #6: deal with new boot files */ 821 vsystem("touch /kernel.config"); 822 vsystem("touch /boot.config"); 823 if (file_readable("/stand/boot.help") && !file_readable("/boot.help")) 824 vsystem("mv /stand/boot.help /"); 825 826 /* Now run all the mtree stuff to fix things up */ 827 vsystem("mtree -deU -f /etc/mtree/BSD.root.dist -p /"); 828 vsystem("mtree -deU -f /etc/mtree/BSD.var.dist -p /var"); 829 vsystem("mtree -deU -f /etc/mtree/BSD.usr.dist -p /usr"); 830 } 831 return DITEM_SUCCESS; 832} 833 834/* Go newfs and/or mount all the filesystems we've been asked to */ 835int 836installFilesystems(dialogMenuItem *self) 837{ 838 int i; 839 Disk *disk; 840 Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev; 841 Device **devs; 842 PartInfo *root; 843 char dname[80]; 844 extern int MakeDevChunk(Chunk *c, char *n); 845 Boolean upgrade = FALSE; 846 847 /* If we've already done this, bail out */ 848 if (!variable_cmp(DISK_LABELLED, "written")) 849 return DITEM_SUCCESS; 850 851 upgrade = !variable_cmp(SYSTEM_STATE, "upgrade"); 852 if (!checkLabels(TRUE, &rootdev, &swapdev, &usrdev, &vardev)) 853 return DITEM_FAILURE; 854 855 if (rootdev) 856 root = (PartInfo *)rootdev->private_data; 857 else 858 root = NULL; 859 860 command_clear(); 861 if (swapdev && RunningAsInit) { 862 /* As the very first thing, try to get ourselves some swap space */ 863 sprintf(dname, "/dev/%s", swapdev->name); 864 if (!Fake && (!MakeDevChunk(swapdev, "/dev") || !file_readable(dname))) { 865 msgConfirm("Unable to make device node for %s in /dev!\n" 866 "The creation of filesystems will be aborted.", dname); 867 return DITEM_FAILURE; 868 } 869 870 if (!Fake) { 871 if (!swapon(dname)) 872 msgNotify("Added %s as initial swap device", dname); 873 else 874 msgConfirm("WARNING! Unable to swap to %s: %s\n" 875 "This may cause the installation to fail at some point\n" 876 "if you don't have a lot of memory.", dname, strerror(errno)); 877 } 878 } 879 880 if (rootdev && RunningAsInit) { 881 /* Next, create and/or mount the root device */ 882 sprintf(dname, "/dev/r%s", rootdev->name); 883 if (!Fake && (!MakeDevChunk(rootdev, "/dev") || !file_readable(dname))) { 884 msgConfirm("Unable to make device node for %s in /dev!\n" 885 "The creation of filesystems will be aborted.", dname); 886 return DITEM_FAILURE; 887 } 888 if (strcmp(root->mountpoint, "/")) 889 msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", rootdev->name, root->mountpoint); 890 891 if (root->newfs && (!upgrade || !msgYesNo("You are upgrading - are you SURE you want to newfs the root partition?"))) { 892 int i; 893 894 msgNotify("Making a new root filesystem on %s", dname); 895 i = vsystem("%s %s", root->newfs_cmd, dname); 896 if (i) { 897 msgConfirm("Unable to make new root filesystem on %s!\n" 898 "Command returned status %d", dname, i); 899 return DITEM_FAILURE; 900 } 901 } 902 else { 903 if (!upgrade) { 904 msgConfirm("Warning: Using existing root partition. It will be assumed\n" 905 "that you have the appropriate device entries already in /dev."); 906 } 907 msgNotify("Checking integrity of existing %s filesystem.", dname); 908 i = vsystem("fsck -y %s", dname); 909 if (i) 910 msgConfirm("Warning: fsck returned status of %d for %s.\n" 911 "This partition may be unsafe to use.", i, dname); 912 } 913 914 /* Switch to block device */ 915 sprintf(dname, "/dev/%s", rootdev->name); 916 if (Mount("/mnt", dname)) { 917 msgConfirm("Unable to mount the root file system on %s! Giving up.", dname); 918 return DITEM_FAILURE; 919 } 920 } 921 922 /* Now buzz through the rest of the partitions and mount them too */ 923 devs = deviceFind(NULL, DEVICE_TYPE_DISK); 924 for (i = 0; devs[i]; i++) { 925 if (!devs[i]->enabled) 926 continue; 927 928 disk = (Disk *)devs[i]->private; 929 if (!disk->chunks) { 930 msgConfirm("No chunk list found for %s!", disk->name); 931 return DITEM_FAILURE; 932 } 933 if (RunningAsInit && root && (root->newfs || upgrade)) { 934 Mkdir("/mnt/dev"); 935 if (!Fake) 936 MakeDevDisk(disk, "/mnt/dev"); 937 } 938 else if (!RunningAsInit && !Fake) 939 MakeDevDisk(disk, "/dev"); 940 941 for (c1 = disk->chunks->part; c1; c1 = c1->next) { 942 if (c1->type == freebsd) { 943 for (c2 = c1->part; c2; c2 = c2->next) { 944 if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) { 945 PartInfo *tmp = (PartInfo *)c2->private_data; 946 947 /* Already did root */ 948 if (c2 == rootdev) 949 continue; 950 951 if (tmp->newfs && (!upgrade || !msgYesNo("You are upgradding - are you SURE you want to newfs /dev/%s?", c2->name))) 952 command_shell_add(tmp->mountpoint, "%s %s/dev/r%s", tmp->newfs_cmd, RunningAsInit ? "/mnt" : "", c2->name); 953 else 954 command_shell_add(tmp->mountpoint, "fsck -y %s/dev/r%s", RunningAsInit ? "/mnt" : "", c2->name); 955 command_func_add(tmp->mountpoint, Mount, c2->name); 956 } 957 else if (c2->type == part && c2->subtype == FS_SWAP) { 958 char fname[80]; 959 int i; 960 961 if (c2 == swapdev) 962 continue; 963 sprintf(fname, "%s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name); 964 i = (Fake || swapon(fname)); 965 if (!i) 966 msgNotify("Added %s as an additional swap device", fname); 967 else 968 msgConfirm("Unable to add %s as a swap device: %s", fname, strerror(errno)); 969 } 970 } 971 } 972 else if (c1->type == fat && c1->private_data && (root->newfs || upgrade)) { 973 char name[FILENAME_MAX]; 974 975 sprintf(name, "%s/%s", RunningAsInit ? "/mnt" : "", ((PartInfo *)c1->private_data)->mountpoint); 976 Mkdir(name); 977 } 978 } 979 } 980 981 if (RunningAsInit) { 982 msgNotify("Copying initial device files.."); 983 /* Copy the boot floppy's dev files */ 984 if ((root->newfs || upgrade) && vsystem("find -x /dev | cpio %s -pdum /mnt", cpioVerbosity())) { 985 msgConfirm("Couldn't clone the /dev files!"); 986 return DITEM_FAILURE; 987 } 988 } 989 990 command_sort(); 991 command_execute(); 992 return DITEM_SUCCESS; 993} 994 995/* Initialize various user-settable values to their defaults */ 996int 997installVarDefaults(dialogMenuItem *self) 998{ 999 char *cp; 1000 1001 /* Set default startup options */ 1002 variable_set2(VAR_RELNAME, RELEASE_NAME); 1003 variable_set2(VAR_CPIO_VERBOSITY, "high"); 1004 variable_set2(VAR_TAPE_BLOCKSIZE, DEFAULT_TAPE_BLOCKSIZE); 1005 variable_set2(VAR_INSTALL_ROOT, "/"); 1006 variable_set2(VAR_INSTALL_CFG, "install.cfg"); 1007 cp = getenv("EDITOR"); 1008 if (!cp) 1009 cp = "/usr/bin/ee"; 1010 variable_set2(VAR_EDITOR, cp); 1011 variable_set2(VAR_FTP_USER, "ftp"); 1012 variable_set2(VAR_BROWSER_PACKAGE, PACKAGE_LYNX); 1013 variable_set2(VAR_BROWSER_BINARY, "/usr/local/bin/lynx"); 1014 variable_set2(VAR_FTP_STATE, "passive"); 1015 variable_set2(VAR_NFS_SECURE, "YES"); 1016 variable_set2(VAR_PKG_TMPDIR, "/usr/tmp"); 1017 variable_set2(VAR_GATED_PKG, PACKAGE_GATED); 1018 variable_set2(VAR_PCNFSD_PKG, PACKAGE_PCNFSD); 1019 variable_set2(VAR_MEDIA_TIMEOUT, itoa(MEDIA_TIMEOUT)); 1020 if (getpid() != 1) 1021 variable_set2(SYSTEM_STATE, "update"); 1022 else 1023 variable_set2(SYSTEM_STATE, "init"); 1024 return DITEM_SUCCESS; 1025} 1026 1027/* Load the environment up from various system configuration files */ 1028void 1029installEnvironment(void) 1030{ 1031 if (file_readable("/etc/rc.conf")) 1032 configEnvironmentRC_conf("/etc/rc.conf"); 1033 if (file_readable("/etc/resolv.conf")) 1034 configEnvironmentResolv("/etc/resolv.conf"); 1035} 1036 1037/* Copy the boot floppy contents into /stand */ 1038Boolean 1039copySelf(void) 1040{ 1041 int i; 1042 1043 if (file_readable("/boot.help")) 1044 vsystem("cp /boot.help /mnt"); 1045 msgWeHaveOutput("Copying the boot floppy to /stand on root filesystem"); 1046 i = vsystem("find -x /stand | cpio %s -pdum /mnt", cpioVerbosity()); 1047 if (i) { 1048 msgConfirm("Copy returned error status of %d!", i); 1049 return FALSE; 1050 } 1051 1052 /* Copy the /etc files into their rightful place */ 1053 if (vsystem("cd /mnt/stand; find etc | cpio %s -pdum /mnt", cpioVerbosity())) { 1054 msgConfirm("Couldn't copy up the /etc files!"); 1055 return TRUE; 1056 } 1057 return TRUE; 1058} 1059 1060static void 1061create_termcap(void) 1062{ 1063 FILE *fp; 1064 1065 const char *caps[] = { 1066 termcap_vt100, termcap_cons25, termcap_cons25_m, termcap_cons25r, 1067 termcap_cons25r_m, termcap_cons25l1, termcap_cons25l1_m, NULL, 1068 }; 1069 const char **cp; 1070 1071 if (!file_readable(TERMCAP_FILE)) { 1072 Mkdir("/usr/share/misc"); 1073 fp = fopen(TERMCAP_FILE, "w"); 1074 if (!fp) { 1075 msgConfirm("Unable to initialize termcap file. Some screen-oriented\nutilities may not work."); 1076 return; 1077 } 1078 cp = caps; 1079 while (*cp) 1080 fprintf(fp, "%s\n", *(cp++)); 1081 fclose(fp); 1082 } 1083} 1084 1085#ifdef SAVE_USERCONFIG 1086static void 1087save_userconfig_to_kernel(char *kern) 1088{ 1089 struct kernel *core, *boot; 1090 struct list *c_isa, *b_isa, *c_dev, *b_dev; 1091 int i, d; 1092 1093 if ((core = uc_open("-incore")) == NULL) { 1094 msgDebug("save_userconf: Can't read in-core information for kernel.\n"); 1095 return; 1096 } 1097 1098 if ((boot = uc_open(kern)) == NULL) { 1099 msgDebug("save_userconf: Can't read device information for kernel image %s\n", kern); 1100 return; 1101 } 1102 1103 msgNotify("Saving any boot -c changes to new kernel..."); 1104 c_isa = uc_getdev(core, "-isa"); 1105 b_isa = uc_getdev(boot, "-isa"); 1106 if (isDebug()) 1107 msgDebug("save_userconf: got %d ISA device entries from core, %d from boot.\n", c_isa->ac, b_isa->ac); 1108 for (d = 0; d < c_isa->ac; d++) { 1109 if (isDebug()) 1110 msgDebug("save_userconf: ISA device loop, c_isa->av[%d] = %s\n", d, c_isa->av[d]); 1111 if (strcmp(c_isa->av[d], "npx0")) { /* special case npx0, which mucks with its id_irq member */ 1112 c_dev = uc_getdev(core, c_isa->av[d]); 1113 b_dev = uc_getdev(boot, b_isa->av[d]); 1114 if (!c_dev || !b_dev) { 1115 msgDebug("save_userconf: c_dev: %x b_dev: %x\n", c_dev, b_dev); 1116 continue; 1117 } 1118 if (isDebug()) 1119 msgDebug("save_userconf: ISA device %s: %d config parameters (core), %d (boot)\n", 1120 c_isa->av[d], c_dev->ac, b_dev->ac); 1121 for (i = 0; i < c_dev->ac; i++) { 1122 if (isDebug()) 1123 msgDebug("save_userconf: c_dev->av[%d] = %s, b_dev->av[%d] = %s\n", i, c_dev->av[i], i, b_dev->av[i]); 1124 if (strcmp(c_dev->av[i], b_dev->av[i])) { 1125 if (isDebug()) 1126 msgDebug("save_userconf: %s (boot) -> %s (core)\n", 1127 c_dev->av[i], b_dev->av[i]); 1128 isa_setdev(boot, c_dev); 1129 } 1130 } 1131 } 1132 else { 1133 if (isDebug()) 1134 msgDebug("skipping npx0\n"); 1135 } 1136 } 1137 if (isDebug()) 1138 msgDebug("Closing kernels\n"); 1139 uc_close(core, 0); 1140 uc_close(boot, 1); 1141} 1142#endif 1143