install.c revision 51234
11541Srgrimes/*
21541Srgrimes * The new sysinstall program.
31541Srgrimes *
41541Srgrimes * This is probably the last program in the `sysinstall' line - the next
51541Srgrimes * generation being essentially a complete rewrite.
61541Srgrimes *
71541Srgrimes * $FreeBSD: head/usr.sbin/sade/install.c 51234 1999-09-13 16:24:08Z jkh $
81541Srgrimes *
91541Srgrimes * Copyright (c) 1995
101541Srgrimes *	Jordan Hubbard.  All rights reserved.
111541Srgrimes *
121541Srgrimes * Redistribution and use in source and binary forms, with or without
131541Srgrimes * modification, are permitted provided that the following conditions
141541Srgrimes * are met:
151541Srgrimes * 1. Redistributions of source code must retain the above copyright
161541Srgrimes *    notice, this list of conditions and the following disclaimer,
171541Srgrimes *    verbatim and that no modifications are made prior to this
181541Srgrimes *    point in the file.
191541Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
201541Srgrimes *    notice, this list of conditions and the following disclaimer in the
211541Srgrimes *    documentation and/or other materials provided with the distribution.
221541Srgrimes *
231541Srgrimes * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
241541Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
251541Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
261541Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
271541Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
281541Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
291541Srgrimes * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
301541Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
311541Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
321541Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
331541Srgrimes * SUCH DAMAGE.
3444456Swpaul *
351541Srgrimes */
361541Srgrimes
371541Srgrimes#include "sysinstall.h"
381541Srgrimes#include <ctype.h>
391541Srgrimes#include <sys/disklabel.h>
401541Srgrimes#include <sys/errno.h>
411541Srgrimes#include <sys/ioctl.h>
421541Srgrimes#include <sys/fcntl.h>
4332350Seivind#include <sys/wait.h>
4441793Sluigi#include <sys/param.h>
4532350Seivind#define MSDOSFS
461541Srgrimes#include <sys/mount.h>
4712693Sphk#include <ufs/ufs/ufsmount.h>
4844078Sdfr#include <msdosfs/msdosfsmount.h>
4912693Sphk#undef MSDOSFS
501541Srgrimes#include <sys/stat.h>
5112693Sphk#include <sys/sysctl.h>
521541Srgrimes#include <unistd.h>
5318892Sbde#include <termios.h>
541541Srgrimes
551541Srgrimesstatic void	create_termcap(void);
561541Srgrimesstatic void	fixit_common(void);
571541Srgrimes
5844165Sjulian#define TERMCAP_FILE	"/usr/share/misc/termcap"
591541Srgrimes
608426Swollmanstatic void	installConfigure(void);
611541Srgrimes
621541SrgrimesBoolean
631541SrgrimescheckLabels(Boolean whinge, Chunk **rdev, Chunk **sdev, Chunk **udev, Chunk **vdev)
641541Srgrimes{
651541Srgrimes    Device **devs;
661541Srgrimes    Boolean status;
671541Srgrimes    Disk *disk;
681541Srgrimes    Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev;
6944078Sdfr    int i;
7012942Swollman
711541Srgrimes    /* Don't allow whinging if noWarn is set */
7212693Sphk    if (variable_get(VAR_NO_WARN))
7312942Swollman	whinge = FALSE;
7412942Swollman
7512942Swollman    status = TRUE;
761541Srgrimes    *rdev = *sdev = *udev = *vdev = rootdev = swapdev = usrdev = vardev = NULL;
7712942Swollman
7812942Swollman    /* We don't need to worry about root/usr/swap if we're already multiuser */
7912942Swollman    if (!RunningAsInit)
8012942Swollman	return status;
8112942Swollman
8212942Swollman    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
8312693Sphk    /* First verify that we have a root device */
841541Srgrimes    for (i = 0; devs[i]; i++) {
851541Srgrimes	if (!devs[i]->enabled)
8611225Swollman	    continue;
8711225Swollman	disk = (Disk *)devs[i]->private;
8811225Swollman	msgDebug("Scanning disk %s for root filesystem\n", disk->name);
8911225Swollman	if (!disk->chunks)
9011225Swollman	    msgFatal("No chunk list found for %s!", disk->name);
9111225Swollman	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
9211225Swollman	    if (c1->type == freebsd) {
9312693Sphk		for (c2 = c1->part; c2; c2 = c2->next) {
9411225Swollman		    if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) {
9511225Swollman			if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/")) {
961541Srgrimes			    if (rootdev) {
9712820Sphk				if (whinge)
981541Srgrimes				    msgConfirm("WARNING:  You have more than one root device set?!\n"
9912693Sphk					       "Using the first one found.");
10012942Swollman				continue;
10112942Swollman			    }
1023282Swollman			    else {
10312942Swollman				rootdev = c2;
10412942Swollman				if (isDebug())
10512942Swollman				    msgDebug("Found rootdev at %s!\n", rootdev->name);
10612942Swollman			    }
10712942Swollman			}
10812942Swollman			else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/usr")) {
10912693Sphk			    if (usrdev) {
11012877Sbde				if (whinge)
11136908Sjulian				    msgConfirm("WARNING:  You have more than one /usr filesystem.\n"
11236908Sjulian					       "Using the first one found.");
11312693Sphk				continue;
11412693Sphk			    }
11512693Sphk			    else {
11612693Sphk				usrdev = c2;
11712693Sphk				if (isDebug())
11832350Seivind				    msgDebug("Found usrdev at %s!\n", usrdev->name);
11912693Sphk			    }
12032350Seivind			}
12112693Sphk			else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/var")) {
1221541Srgrimes			    if (vardev) {
1231541Srgrimes				if (whinge)
1241541Srgrimes				    msgConfirm("WARNING:  You have more than one /var filesystem.\n"
1251541Srgrimes					       "Using the first one found.");
1261541Srgrimes				continue;
1271541Srgrimes			    }
1281541Srgrimes			    else {
1291541Srgrimes				vardev = c2;
1301541Srgrimes				if (isDebug())
13111225Swollman				    msgDebug("Found vardev at %s!\n", vardev->name);
13211225Swollman			    }
1331541Srgrimes			}
1341541Srgrimes		    }
13511225Swollman		}
1361541Srgrimes	    }
13711225Swollman	}
13834961Sphk    }
13911225Swollman
1401541Srgrimes    /* Now check for swap devices */
1411541Srgrimes    for (i = 0; devs[i]; i++) {
1421541Srgrimes	if (!devs[i]->enabled)
1431541Srgrimes	    continue;
1441541Srgrimes	disk = (Disk *)devs[i]->private;
1451541Srgrimes	msgDebug("Scanning disk %s for swap partitions\n", disk->name);
1461541Srgrimes	if (!disk->chunks)
1475196Swollman	    msgFatal("No chunk list found for %s!", disk->name);
1481541Srgrimes	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
1491541Srgrimes	    if (c1->type == freebsd) {
1501541Srgrimes		for (c2 = c1->part; c2; c2 = c2->next) {
1511541Srgrimes		    if (c2->type == part && c2->subtype == FS_SWAP && !swapdev) {
1521541Srgrimes			swapdev = c2;
1531541Srgrimes			if (isDebug())
1541541Srgrimes			    msgDebug("Found swapdev at %s!\n", swapdev->name);
1551541Srgrimes			break;
15612693Sphk		    }
1571541Srgrimes		}
1581541Srgrimes	    }
1591541Srgrimes	}
16011225Swollman    }
1611541Srgrimes
1621541Srgrimes    /* Copy our values over */
1631541Srgrimes    *rdev = rootdev;
1641541Srgrimes    *sdev = swapdev;
1651541Srgrimes    *udev = usrdev;
1661541Srgrimes    *vdev = vardev;
1671541Srgrimes
1681541Srgrimes    if (!rootdev && whinge) {
1691541Srgrimes	msgConfirm("No root device found - you must label a partition as /\n"
1701541Srgrimes		   "in the label editor.");
1711541Srgrimes	status = FALSE;
1721541Srgrimes    }
1731541Srgrimes    if (!swapdev && whinge) {
1741541Srgrimes	msgConfirm("No swap devices found - you must create at least one\n"
1751541Srgrimes		   "swap partition.");
1761541Srgrimes	status = FALSE;
1771541Srgrimes    }
1781541Srgrimes    return status;
1791541Srgrimes}
1801541Srgrimes
1811541Srgrimesstatic int
1821541SrgrimesinstallInitial(void)
1831541Srgrimes{
1841541Srgrimes    static Boolean alreadyDone = FALSE;
18534961Sphk    int status = DITEM_SUCCESS;
1861541Srgrimes
1871541Srgrimes    if (alreadyDone)
1881541Srgrimes	return DITEM_SUCCESS;
1891541Srgrimes
1901541Srgrimes    if (!variable_get(DISK_LABELLED)) {
19136908Sjulian	msgConfirm("You need to assign disk labels before you can proceed with\n"
19236908Sjulian		   "the installation.");
1931541Srgrimes	return DITEM_FAILURE;
1941541Srgrimes    }
1951541Srgrimes    /* If it's labelled, assume it's also partitioned */
1961541Srgrimes    if (!variable_get(DISK_PARTITIONED))
1971541Srgrimes	variable_set2(DISK_PARTITIONED, "yes", 0);
1986568Sdg
1991541Srgrimes    /* If we refuse to proceed, bail. */
2001541Srgrimes    dialog_clear_norefresh();
2011541Srgrimes    if (!variable_get(VAR_NO_WARN))
2021541Srgrimes	if (msgYesNo(
2031541Srgrimes	    "Last Chance!  Are you SURE you want continue the installation?\n\n"
2041541Srgrimes	     "If you're running this on a disk with data you wish to save\n"
2051541Srgrimes	     "then WE STRONGLY ENCOURAGE YOU TO MAKE PROPER BACKUPS before\n"
2061541Srgrimes	     "proceeding!\n\n"
2071541Srgrimes	     "We can take no responsibility for lost disk contents!") != 0)
2081541Srgrimes	return DITEM_FAILURE | DITEM_RESTORE;
2091541Srgrimes
2101541Srgrimes    if (DITEM_STATUS(diskLabelCommit(NULL)) != DITEM_SUCCESS) {
2111541Srgrimes	msgConfirm("Couldn't make filesystems properly.  Aborting.");
2121541Srgrimes	return DITEM_FAILURE;
2131541Srgrimes    }
2141541Srgrimes
2151541Srgrimes    if (!copySelf()) {
2161541Srgrimes	msgConfirm("installInitial: Couldn't clone the boot floppy onto the\n"
2171541Srgrimes		   "root file system.  Aborting!");
2181541Srgrimes	return DITEM_FAILURE;
21911225Swollman    }
22013926Swollman
22132350Seivind    if (chroot("/mnt") == -1) {
22213926Swollman	msgConfirm("installInitial: Unable to chroot to %s - this is bad!",
22313926Swollman		   "/mnt");
22413926Swollman	return DITEM_FAILURE;
22513926Swollman    }
22613926Swollman
22713926Swollman    chdir("/");
22813926Swollman    variable_set2(RUNNING_ON_ROOT, "yes", 0);
22913926Swollman
23013926Swollman    /* Configure various files in /etc */
23116576Speter    if (DITEM_STATUS(configResolv(NULL)) == DITEM_FAILURE)
23213926Swollman	status = DITEM_FAILURE;
23313926Swollman    if (DITEM_STATUS(configFstab(NULL)) == DITEM_FAILURE)
23413926Swollman	status = DITEM_FAILURE;
23513926Swollman
23616576Speter    /* stick a helpful shell over on the 4th VTY */
23713926Swollman    systemCreateHoloshell();
23832350Seivind
23913926Swollman    alreadyDone = TRUE;
2401541Srgrimes    return status;
2411541Srgrimes}
2421541Srgrimes
2431541Srgrimesint
2441541SrgrimesinstallFixitHoloShell(dialogMenuItem *self)
2451541Srgrimes{
2461541Srgrimes    systemCreateHoloshell();
2471541Srgrimes    return DITEM_SUCCESS;
2481541Srgrimes}
2491541Srgrimes
2501541Srgrimesint
2511541SrgrimesinstallFixitCDROM(dialogMenuItem *self)
2521541Srgrimes{
2531541Srgrimes    struct stat sb;
2541541Srgrimes
2551541Srgrimes    if (!RunningAsInit)
2568090Spst	return DITEM_SUCCESS;
2571541Srgrimes
2581541Srgrimes    variable_set2(SYSTEM_STATE, "fixit", 0);
2591541Srgrimes    (void)unlink("/mnt2");
2601541Srgrimes    (void)rmdir("/mnt2");
2611541Srgrimes
2621541Srgrimes    while (1) {
2631541Srgrimes	msgConfirm("Please insert a FreeBSD live filesystem CDROM and press return");
2641541Srgrimes	if (DITEM_STATUS(mediaSetCDROM(NULL)) != DITEM_SUCCESS || !mediaDevice || !mediaDevice->init(mediaDevice)) {
26511225Swollman	    /* If we can't initialize it, it's probably not a FreeBSD CDROM so punt on it */
2661541Srgrimes	    mediaClose();
2671541Srgrimes	    if (msgYesNo("Unable to mount the CDROM - do you want to try again?") != 0)
2681541Srgrimes		return DITEM_FAILURE;
2691541Srgrimes	}
2701541Srgrimes	else
2711541Srgrimes	    break;
2721541Srgrimes    }
2731541Srgrimes
2741541Srgrimes    /* Since the fixit code expects everything to be in /mnt2, and the CDROM mounting stuff /dist, do
2751541Srgrimes     * a little kludge dance here..
2761541Srgrimes     */
2771541Srgrimes    if (symlink("/dist", "/mnt2")) {
2781541Srgrimes	msgConfirm("Unable to symlink /mnt2 to the CDROM mount point.  Please report this\n"
2791541Srgrimes		   "unexpected failure to freebsd-bugs@FreeBSD.org.");
2801541Srgrimes	return DITEM_FAILURE;
2811541Srgrimes    }
2821541Srgrimes
28336908Sjulian    /*
2841541Srgrimes     * If /tmp points to /mnt2/tmp from a previous fixit floppy session, it's
2851541Srgrimes     * not very good for us if we point it to the CDROM now.  Rather make it
2861541Srgrimes     * a directory in the root MFS then.  Experienced admins will still be
2871541Srgrimes     * able to mount their disk's /tmp over this if they need.
2881541Srgrimes     */
2891541Srgrimes    if (lstat("/tmp", &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFLNK)
2901541Srgrimes	(void)unlink("/tmp");
2911541Srgrimes    Mkdir("/tmp");
2921541Srgrimes
2931541Srgrimes    /*
2941541Srgrimes     * Since setuid binaries ignore LD_LIBRARY_PATH, we indeed need the
29544456Swpaul     * ld.so.hints file.  Fortunately, it's fairly small (~ 3 KB).
2961541Srgrimes     */
2971541Srgrimes    if (!file_readable("/var/run/ld.so.hints")) {
2981541Srgrimes	Mkdir("/var/run");
2991541Srgrimes	if (vsystem("/mnt2/sbin/ldconfig -s /mnt2/usr/lib")) {
3008384Sdg	    msgConfirm("Warning: ldconfig could not create the ld.so hints file.\n"
30116341Sdg		       "Dynamic executables from the CDROM likely won't work.");
30244165Sjulian	}
30344165Sjulian    }
30444165Sjulian
30544165Sjulian    /* Yet more iggly hardcoded pathnames. */
3061541Srgrimes    Mkdir("/usr/libexec");
3071541Srgrimes    if (!file_readable("/usr/libexec/ld.so")) {
3081541Srgrimes	if (symlink("/mnt2/usr/libexec/ld.so", "/usr/libexec/ld.so"))
3091541Srgrimes	    msgDebug("Couldn't link to ld.so - not necessarily a problem for ELF\n");
3108384Sdg    }
3118384Sdg    if (!file_readable("/usr/libexec/ld-elf.so.1")) {
3128384Sdg	if (symlink("/mnt2/usr/libexec/ld-elf.so.1", "/usr/libexec/ld-elf.so.1")) {
3131541Srgrimes	    msgConfirm("Warning: could not create the symlink for ld-elf.so.1\n"
3141541Srgrimes		       "Dynamic executables from the CDROM likely won't work.");
3151541Srgrimes	}
3161541Srgrimes    }
3171541Srgrimes    /* optional nicety */
3181541Srgrimes    if (!file_readable("/usr/bin/vi"))
3191541Srgrimes	symlink("/mnt2/usr/bin/vi", "/usr/bin/vi");
3201541Srgrimes    fixit_common();
3211541Srgrimes    mediaClose();
3221541Srgrimes    msgConfirm("Please remove the FreeBSD fixit CDROM now.");
3231541Srgrimes    return DITEM_SUCCESS;
3241541Srgrimes}
3251541Srgrimes
3261541Srgrimesint
3271541SrgrimesinstallFixitFloppy(dialogMenuItem *self)
3281541Srgrimes{
3293514Swollman    struct ufs_args args;
3301541Srgrimes    extern char *distWanted;
3311541Srgrimes
3321541Srgrimes    if (!RunningAsInit)
3331541Srgrimes	return DITEM_SUCCESS;
3341541Srgrimes
3353514Swollman    /* Try to open the floppy drive */
3361541Srgrimes    if (DITEM_STATUS(mediaSetFloppy(NULL)) == DITEM_FAILURE || !mediaDevice) {
33742866Sfenner	msgConfirm("Unable to set media device to floppy.");
3381541Srgrimes	mediaClose();
3391541Srgrimes	return DITEM_FAILURE;
3401541Srgrimes    }
3418384Sdg
3421541Srgrimes    memset(&args, 0, sizeof(args));
3431541Srgrimes    args.fspec = mediaDevice->devname;
3441541Srgrimes    mediaDevice->private = "/mnt2";
3451541Srgrimes    distWanted = NULL;
3461541Srgrimes    Mkdir("/mnt2");
3471541Srgrimes
3481541Srgrimes    variable_set2(SYSTEM_STATE, "fixit", 0);
3491541Srgrimes
35042775Sfenner    while (1) {
3513311Sphk	if (!mediaDevice->init(mediaDevice)) {
3523311Sphk	    if (msgYesNo("The attempt to mount the fixit floppy failed, bad floppy\n"
3531541Srgrimes			 "or unclean filesystem.  Do you want to try again?"))
3541541Srgrimes		return DITEM_FAILURE;
3551541Srgrimes	}
35636308Sphk	else
35736308Sphk	    break;
35836308Sphk    }
3591541Srgrimes    if (!directory_exists("/tmp"))
3601541Srgrimes	(void)symlink("/mnt2/tmp", "/tmp");
3611541Srgrimes    fixit_common();
3621541Srgrimes    mediaClose();
3631541Srgrimes    msgConfirm("Please remove the fixit floppy now.");
3641541Srgrimes    return DITEM_SUCCESS;
3651541Srgrimes}
3661541Srgrimes
36734961Sphk/*
3681541Srgrimes * The common code for both fixit variants.
36916206Sbde */
3701541Srgrimesstatic void
3711541Srgrimesfixit_common(void)
3721541Srgrimes{
3731541Srgrimes    pid_t child;
3741541Srgrimes    int waitstatus;
3751541Srgrimes
3761541Srgrimes    if (!directory_exists("/var/tmp/vi.recover")) {
3771541Srgrimes	if (DITEM_STATUS(Mkdir("/var/tmp/vi.recover")) != DITEM_SUCCESS) {
3781541Srgrimes	    msgConfirm("Warning:  Was unable to create a /var/tmp/vi.recover directory.\n"
3791541Srgrimes		       "vi will kvetch and moan about it as a result but should still\n"
3801541Srgrimes		       "be essentially usable.");
3811541Srgrimes	}
38234961Sphk    }
38334961Sphk    if (!directory_exists("/bin"))
3841541Srgrimes	(void)Mkdir("/bin");
38514761Sfenner    (void)symlink("/stand/sh", "/bin/sh");
38636908Sjulian    /* Link the /etc/ files */
38736908Sjulian    if (DITEM_STATUS(Mkdir("/etc")) != DITEM_SUCCESS)
3881541Srgrimes	msgConfirm("Unable to create an /etc directory!  Things are weird on this floppy..");
3891541Srgrimes    else if ((symlink("/mnt2/etc/spwd.db", "/etc/spwd.db") == -1 && errno != EEXIST) ||
3901541Srgrimes	     (symlink("/mnt2/etc/protocols", "/etc/protocols") == -1 && errno != EEXIST) ||
3911541Srgrimes	     (symlink("/mnt2/etc/services", "/etc/services") == -1 && errno != EEXIST))
3921541Srgrimes	msgConfirm("Couldn't symlink the /etc/ files!  I'm not sure I like this..");
3931541Srgrimes    if (!file_readable(TERMCAP_FILE))
3941541Srgrimes	create_termcap();
3951541Srgrimes    if (!(child = fork())) {
3961541Srgrimes	int i, fd;
3971541Srgrimes	struct termios foo;
3981541Srgrimes	extern int login_tty(int);
3991541Srgrimes
4001541Srgrimes	ioctl(0, TIOCNOTTY, NULL);
4011541Srgrimes	for (i = getdtablesize(); i >= 0; --i)
4021541Srgrimes	    close(i);
40312693Sphk	fd = open("/dev/ttyv3", O_RDWR);
40431884Sbde	ioctl(0, TIOCSCTTY, &fd);
4051541Srgrimes	dup2(0, 1);
4061541Srgrimes	dup2(0, 2);
4071541Srgrimes	DebugFD = 2;
4081541Srgrimes	if (login_tty(fd) == -1)
4091541Srgrimes	    msgDebug("fixit: I can't set the controlling terminal.\n");
4101541Srgrimes
4111541Srgrimes	signal(SIGTTOU, SIG_IGN);
4121541Srgrimes	if (tcgetattr(0, &foo) != -1) {
4131541Srgrimes	    foo.c_cc[VERASE] = '\010';
4141541Srgrimes	    if (tcsetattr(0, TCSANOW, &foo) == -1)
4151541Srgrimes		msgDebug("fixit shell: Unable to set erase character.\n");
4161541Srgrimes	}
4171541Srgrimes	else
41844165Sjulian	    msgDebug("fixit shell: Unable to get terminal attributes!\n");
41944165Sjulian	setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/stand:"
4201541Srgrimes	       "/mnt2/stand:/mnt2/bin:/mnt2/sbin:/mnt2/usr/bin:/mnt2/usr/sbin", 1);
4211541Srgrimes	/* use the .profile from the fixit medium */
4221541Srgrimes	setenv("HOME", "/mnt2", 1);
4231541Srgrimes	chdir("/mnt2");
4241541Srgrimes	execlp("sh", "-sh", 0);
42532350Seivind	msgDebug("fixit shell: Failed to execute shell!\n");
4261541Srgrimes	_exit(1);;
4271541Srgrimes    }
4281541Srgrimes    else {
42932350Seivind	msgNotify("Waiting for fixit shell to exit.  Go to VTY4 now by\n"
4301541Srgrimes		  "typing ALT-F4.  When you are done, type ``exit'' to exit\n"
4311541Srgrimes		  "the fixit shell and be returned here.");
4321541Srgrimes	(void)waitpid(child, &waitstatus, 0);
4331541Srgrimes    }
4341541Srgrimes    dialog_clear();
4358426Swollman}
4368426Swollman
43732350Seivind
43832350Seivindint
4391541SrgrimesinstallExpress(dialogMenuItem *self)
4401541Srgrimes{
4411541Srgrimes    int i;
4421541Srgrimes
4431541Srgrimes    variable_set2(SYSTEM_STATE, "express", 0);
4441541Srgrimes#ifndef __alpha__
4451541Srgrimes    if (DITEM_STATUS((i = diskPartitionEditor(self))) == DITEM_FAILURE)
4461541Srgrimes	return i;
4471541Srgrimes#endif
4481541Srgrimes
4491541Srgrimes    if (DITEM_STATUS((i = diskLabelEditor(self))) == DITEM_FAILURE)
4501541Srgrimes	return i;
4511541Srgrimes
4521541Srgrimes    dialog_clear_norefresh();
4531541Srgrimes    if (DITEM_STATUS((i = installCommit(self))) == DITEM_SUCCESS) {
4541541Srgrimes	i |= DITEM_LEAVE_MENU;
4551541Srgrimes	/* Give user the option of one last configuration spree */
4561541Srgrimes	installConfigure();
4571541Srgrimes    }
4581541Srgrimes    return i | DITEM_RESTORE;
4591541Srgrimes}
4601541Srgrimes
4611541Srgrimes/* Novice mode installation */
4621541Srgrimesint
4631541SrgrimesinstallNovice(dialogMenuItem *self)
4641541Srgrimes{
4651541Srgrimes    int i, tries = 0;
4661541Srgrimes    Device **devs;
4671541Srgrimes
4681541Srgrimes    variable_set2(SYSTEM_STATE, "novice", 0);
4691541Srgrimes#ifndef __alpha__
4708384Sdg    dialog_clear_norefresh();
4718384Sdg    msgConfirm("In the next menu, you will need to set up a DOS-style (\"fdisk\") partitioning\n"
47220525Sbde	       "scheme for your hard disk.  If you simply wish to devote all disk space\n"
47341793Sluigi	       "to FreeBSD (overwriting anything else that might be on the disk(s) selected)\n"
47441793Sluigi	       "then use the (A)ll command to select the default partitioning scheme followed\n"
47541793Sluigi	       "by a (Q)uit.  If you wish to allocate only free space to FreeBSD, move to a\n"
47641793Sluigi	       "partition marked \"unused\" and use the (C)reate command.");
47741793Sluigi
47841793Sluiginodisks:
47941793Sluigi    if (DITEM_STATUS(diskPartitionEditor(self)) == DITEM_FAILURE)
48041793Sluigi	return DITEM_FAILURE;
4811541Srgrimes
48241793Sluigi    if (diskGetSelectCount(&devs) <= 0 && tries < 3) {
4831541Srgrimes	msgConfirm("You need to select some disks to operate on!  Be sure to use SPACE\n"
4841541Srgrimes		   "instead of RETURN in the disk selection menu when selecting a disk.");
4851541Srgrimes	++tries;
4861541Srgrimes	goto nodisks;
4871541Srgrimes    }
48812693Sphk#endif
48912693Sphk
49012693Sphk    dialog_clear_norefresh();
49112693Sphk#ifdef __alpha__
4921541Srgrimes    msgConfirm("First, you need to create BSD partitions on the disk which you are\n"
4931541Srgrimes	       "installing to.  If you have a reasonable amount of disk space (200MB or more)\n"
49412693Sphk	       "and don't have any special requirements, simply use the (A)uto command to\n"
49512693Sphk	       "allocate space automatically.  If you have more specific needs or just don't\n"
49612693Sphk	       "care for the layout chosen by (A)uto, press F1 for more information on\n"
49712693Sphk	       "manual layout.");
4981541Srgrimes#else
4991541Srgrimes    msgConfirm("First, you need to create BSD partitions inside of the fdisk partition(s)\n"
5001541Srgrimes	       "just created.  If you have a reasonable amount of disk space (200MB or more)\n"
5014069Swollman	       "and don't have any special requirements, simply use the (A)uto command to\n"
5027088Swollman	       "allocate space automatically.  If you have more specific needs or just don't\n"
50312693Sphk	       "care for the layout chosen by (A)uto, press F1 for more information on\n"
50412693Sphk	       "manual layout.");
5051541Srgrimes#endif
5061541Srgrimes
5071541Srgrimes    if (DITEM_STATUS(diskLabelEditor(self)) == DITEM_FAILURE)
50819794Sfenner	return DITEM_FAILURE;
50919794Sfenner
5101541Srgrimes    dialog_clear_norefresh();
5111541Srgrimes    if (DITEM_STATUS((i = installCommit(self))) == DITEM_FAILURE) {
5121541Srgrimes	dialog_clear_norefresh();
5131541Srgrimes	msgConfirm("Installation completed with some errors.  You may wish to\n"
5141541Srgrimes		   "scroll through the debugging messages on VTY1 with the\n"
51542486Sluigi		   "scroll-lock feature.  You can also chose \"No\" at the next\n"
51639389Sfenner		   "prompt and go back into the installation menus to try and retry\n"
51739389Sfenner		   "whichever operations have failed.");
51839389Sfenner	return i | DITEM_RESTORE;
51939389Sfenner
52039389Sfenner    }
52139389Sfenner    else {
52239389Sfenner	dialog_clear_norefresh();
52339389Sfenner	msgConfirm("Congratulations!  You now have FreeBSD installed on your system.\n\n"
52442486Sluigi		   "We will now move on to the final configuration questions.\n"
5251541Srgrimes		   "For any option you do not wish to configure, simply select\n"
5261541Srgrimes		   "No.\n\n"
52739389Sfenner		   "If you wish to re-enter this utility after the system is up, you\n"
52839389Sfenner		   "may do so by typing: /stand/sysinstall.");
52939389Sfenner    }
53039389Sfenner    if (mediaDevice->type != DEVICE_TYPE_FTP && mediaDevice->type != DEVICE_TYPE_NFS) {
53139389Sfenner	if (!msgYesNo("Would you like to configure any Ethernet or SLIP/PPP network devices?")) {
53239389Sfenner	    Device *tmp;
53339389Sfenner
53439389Sfenner	    dialog_clear_norefresh();
53539389Sfenner	    tmp = tcpDeviceSelect();
53639389Sfenner	    dialog_clear_norefresh();
53739389Sfenner	    if (tmp && !((DevInfo *)tmp->private)->use_dhcp && !msgYesNo("Would you like to bring the %s interface up right now?", tmp->name))
53839389Sfenner		if (!tmp->init(tmp))
5398384Sdg		    msgConfirm("Initialization of %s device failed.", tmp->name);
5408384Sdg	}
5411541Srgrimes    }
54234961Sphk
5431541Srgrimes    dialog_clear_norefresh();
5441541Srgrimes    if (!msgYesNo("Will this machine be an IP gateway (e.g. will it forward packets\n"
5451541Srgrimes		  "between interfaces)?"))
5461541Srgrimes	variable_set2("gateway_enable", "YES", 1);
5471541Srgrimes
5481541Srgrimes    dialog_clear_norefresh();
5491541Srgrimes    if (!msgYesNo("Do you want to allow anonymous FTP connections to this machine?"))
5501541Srgrimes	configAnonFTP(self);
5511541Srgrimes
5521541Srgrimes    dialog_clear_norefresh();
5531541Srgrimes    if (!msgYesNo("Do you want to configure this machine as an NFS server?"))
5541541Srgrimes	configNFSServer(self);
5551541Srgrimes
5561541Srgrimes    dialog_clear_norefresh();
5571541Srgrimes    if (!msgYesNo("Do you want to configure this machine as an NFS client?"))
5588384Sdg	variable_set2("nfs_client_enable", "YES", 1);
5598384Sdg
5601541Srgrimes    dialog_clear_norefresh();
5611541Srgrimes    if (!msgYesNo("Would you like to customize your system console settings?")) {
5623282Swollman	WINDOW *w = savescr();
5633282Swollman
5643282Swollman	dmenuOpenSimple(&MenuSyscons, FALSE);
56512693Sphk	restorescr(w);
56612693Sphk    }
56712693Sphk
56812693Sphk    dialog_clear_norefresh();
5693282Swollman    if (!msgYesNo("Would you like to set this machine's time zone now?")) {
5703282Swollman	WINDOW *w = savescr();
5713282Swollman
5723282Swollman	dialog_clear();
5733282Swollman	systemExecute("tzsetup");
5743282Swollman	restorescr(w);
5755101Swollman    }
57612693Sphk
57712693Sphk#ifdef __i386__
57812693Sphk    dialog_clear_norefresh();
57912693Sphk    if (!msgYesNo("Would you like to enable Linux binary compatibility?"))
5803282Swollman	(void)configLinux(self);
5813282Swollman#endif
5823282Swollman
5833282Swollman    dialog_clear_norefresh();
5843282Swollman    if (!msgYesNo("Does this system have a mouse attached to it?")) {
58512693Sphk	WINDOW *w = savescr();
5863282Swollman
58712693Sphk	dmenuOpenSimple(&MenuMouse, FALSE);
58812693Sphk	restorescr(w);
5893282Swollman    }
5908384Sdg
5918384Sdg    /* Now would be a good time to checkpoint the configuration data */
5923282Swollman    configRC_conf();
5934069Swollman    sync();
5948876Srgrimes
5957088Swollman    if (directory_exists("/usr/X11R6")) {
5964069Swollman	dialog_clear_norefresh();
5973282Swollman	if (!msgYesNo("Would you like to configure your X server at this time?"))
5983282Swollman	    (void)configXSetup(self);
5998384Sdg    }
6003282Swollman
6018384Sdg    dialog_clear_norefresh();
6023282Swollman    if (!msgYesNo("The FreeBSD package collection is a collection of hundreds of ready-to-run\n"
6031541Srgrimes		  "applications, from text editors to games to WEB servers and more.  Would you\n"
6041541Srgrimes		  "like to browse the collection now?"))
6058384Sdg	(void)configPackages(self);
6068384Sdg
6071541Srgrimes    dialog_clear_norefresh();
6081541Srgrimes    if (!msgYesNo("Would you like to add any initial user accounts to the system?\n"
6091541Srgrimes		  "Adding at least one account for yourself at this stage is suggested\n"
6108384Sdg		  "since working as the \"root\" user is dangerous (it is easy to do\n"
61116341Sdg		  "things which adversely affect the entire system)."))
6121541Srgrimes	(void)configUsers(self);
6131541Srgrimes
6141541Srgrimes    dialog_clear_norefresh();
6151541Srgrimes    msgConfirm("Now you must set the system manager's password.\n"
6161541Srgrimes	       "This is the password you'll use to log in as \"root\".");
61732350Seivind    {
6181541Srgrimes	WINDOW *w = savescr();
6191541Srgrimes
6201541Srgrimes	if (!systemExecute("passwd root"))
6211541Srgrimes	    variable_set2("root_password", "YES", 0);
6221541Srgrimes	restorescr(w);
6231541Srgrimes    }
6241541Srgrimes
6251541Srgrimes    /* XXX Put whatever other nice configuration questions you'd like to ask the user here XXX */
6261541Srgrimes
6271541Srgrimes    /* Give user the option of one last configuration spree */
6281541Srgrimes    dialog_clear_norefresh();
6291541Srgrimes    installConfigure();
6301541Srgrimes
6311541Srgrimes    return DITEM_LEAVE_MENU | DITEM_RESTORE;
6321541Srgrimes}
6331541Srgrimes
6341541Srgrimes/* The version of commit we call from the Install Custom menu */
6351541Srgrimesint
6361541SrgrimesinstallCustomCommit(dialogMenuItem *self)
6371541Srgrimes{
6381541Srgrimes    int i;
6391541Srgrimes
6401541Srgrimes    dialog_clear_norefresh();
6411541Srgrimes    i = installCommit(self);
6421541Srgrimes    if (DITEM_STATUS(i) == DITEM_SUCCESS) {
6431541Srgrimes	/* Give user the option of one last configuration spree */
6441541Srgrimes	installConfigure();
6451541Srgrimes	return i;
6461541Srgrimes    }
6471541Srgrimes    else
6481541Srgrimes	msgConfirm("The commit operation completed with errors.  Not\n"
6491541Srgrimes		   "updating /etc files.");
6504069Swollman    return i;
6511541Srgrimes}
6521541Srgrimes
6531541Srgrimes/*
6545101Swollman * What happens when we finally decide to going ahead with the installation.
6551541Srgrimes *
6561541Srgrimes * This is broken into multiple stages so that the user can do a full
6571541Srgrimes * installation but come back here again to load more distributions,
6584069Swollman * perhaps from a different media type.  This would allow, for
65912693Sphk * example, the user to load the majority of the system from CDROM and
6604069Swollman * then use ftp to load just the DES dist.
66112693Sphk */
6624069Swollmanint
66312693SphkinstallCommit(dialogMenuItem *self)
6644069Swollman{
6654069Swollman    int i;
66612693Sphk    char *str;
6674069Swollman
6687088Swollman    if (!Dists)
6694069Swollman	distConfig(NULL);
67012693Sphk
6714069Swollman    if (!Dists)
6721541Srgrimes	if (!dmenuOpenSimple(&MenuDistributions, FALSE) && !Dists)
6731541Srgrimes	    return DITEM_FAILURE | DITEM_RESTORE;
6741541Srgrimes
6751541Srgrimes    if (!mediaVerify())
6765195Swollman	return DITEM_FAILURE | DITEM_RESTORE;
6775195Swollman
6785195Swollman    str = variable_get(SYSTEM_STATE);
6795195Swollman    if (isDebug())
6805195Swollman	msgDebug("installCommit: System state is `%s'\n", str);
68125822Stegge
68236908Sjulian    /* Installation stuff we wouldn't do to a running system */
68336908Sjulian    if (RunningAsInit && DITEM_STATUS((i = installInitial())) == DITEM_FAILURE)
6845195Swollman	return i;
6855195Swollman
6865195Swollmantry_media:
687    if (!mediaDevice->init(mediaDevice)) {
688	if (!msgYesNo("Unable to initialize selected media. Would you like to\n"
689		      "adjust your media configuration and try again?")) {
690	    mediaDevice = NULL;
691	    if (!mediaVerify())
692		return DITEM_FAILURE | DITEM_RESTORE;
693	    else
694		goto try_media;
695	}
696	else
697	    return DITEM_FAILURE | DITEM_RESTORE;
698    }
699
700    /* Now go get it all */
701    i = distExtractAll(self);
702
703    /* When running as init, *now* it's safe to grab the rc.foo vars */
704    installEnvironment();
705
706    variable_set2(SYSTEM_STATE, DITEM_STATUS(i) == DITEM_FAILURE ? "error-install" : "full-install", 0);
707
708    return i | DITEM_RESTORE;
709}
710
711static void
712installConfigure(void)
713{
714    /* Final menu of last resort */
715    dialog_clear_norefresh();
716    if (!msgYesNo("Visit the general configuration menu for a chance to set\n"
717		  "any last options?")) {
718	WINDOW *w = savescr();
719
720	dmenuOpenSimple(&MenuConfigure, FALSE);
721	restorescr(w);
722    }
723    configRC_conf();
724    sync();
725}
726
727int
728installFixupBin(dialogMenuItem *self)
729{
730    Device **devs;
731    char *cp;
732    int i;
733
734    /* All of this is done only as init, just to be safe */
735    if (RunningAsInit) {
736	/* Fix up kernel first */
737	if (!file_readable("/kernel")) {
738	    char *generic_kernel = "/kernel.GENERIC";
739	    if (file_readable(generic_kernel)) {
740		if (vsystem("cp -p %s /kernel", generic_kernel)) {
741		    msgConfirm("Unable to copy /kernel into place!");
742		    return DITEM_FAILURE;
743		}
744#ifndef __alpha__
745                /* Snapshot any boot -c changes back to the new kernel */
746		cp = variable_get(VAR_KGET);
747		if (cp && (*cp == 'Y' || *cp == 'y')) {
748		    if (kget("/boot/kernel.conf")) {
749			msgConfirm("Kernel copied OK, but unable to save boot -c changes\n"
750				   "to it.  See the debug screen (ALT-F2) for details.");
751		    }
752		    else if (file_readable("/boot/kernel.conf")) {
753			FILE *fp;
754
755			if ((fp = fopen("/boot/loader.conf", "a")) != NULL) {
756			    fprintf(fp, "# -- sysinstall generated deltas -- #\n");
757			    fprintf(fp, "userconfig_script_load=\"YES\"\n");
758			    if (!OnVTY)
759				fprintf(fp, "console=\"comconsole\"\n");
760			    fclose(fp);
761			}
762		    }
763		}
764#endif
765	    }
766	    else {
767		msgConfirm("Can't find a kernel image to link to on the root file system!\n"
768			   "You're going to have a hard time getting this system to\n"
769			   "boot from the hard disk, I'm afraid!");
770		return DITEM_FAILURE;
771	    }
772	}
773
774	/* BOGON #1: Resurrect /dev after bin distribution screws it up */
775	msgNotify("Remaking all devices.. Please wait!");
776	if (vsystem("cd /dev; sh MAKEDEV all")) {
777	    msgConfirm("MAKEDEV returned non-zero status");
778	    return DITEM_FAILURE;
779	}
780
781	msgNotify("Resurrecting /dev entries for slices..");
782	devs = deviceFind(NULL, DEVICE_TYPE_DISK);
783	if (!devs)
784	    msgFatal("Couldn't get a disk device list!");
785
786	/* Resurrect the slices that the former clobbered */
787	for (i = 0; devs[i]; i++) {
788	    Disk *disk = (Disk *)devs[i]->private;
789	    Chunk *c1;
790
791	    if (!devs[i]->enabled)
792		continue;
793	    if (!disk->chunks)
794		msgFatal("No chunk list found for %s!", disk->name);
795	    for (c1 = disk->chunks->part; c1; c1 = c1->next) {
796		if (c1->type == freebsd) {
797		    msgNotify("Making slice entries for %s", c1->name);
798		    if (vsystem("cd /dev; sh MAKEDEV %sh", c1->name)) {
799			msgConfirm("Unable to make slice entries for %s!", c1->name);
800			return DITEM_FAILURE;
801		    }
802		}
803	    }
804	}
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	/* Now run all the mtree stuff to fix things up */
821        vsystem("mtree -deU -f /etc/mtree/BSD.root.dist -p /");
822        vsystem("mtree -deU -f /etc/mtree/BSD.var.dist -p /var");
823        vsystem("mtree -deU -f /etc/mtree/BSD.usr.dist -p /usr");
824
825	/* Do all the last ugly work-arounds here */
826    }
827    return DITEM_SUCCESS;
828}
829
830/* Fix side-effects from the the XFree86 installation */
831int
832installFixupXFree(dialogMenuItem *self)
833{
834    /* BOGON #1:  XFree86 requires various specialized fixups */
835    if (directory_exists("/usr/X11R6")) {
836	msgNotify("Fixing permissions in XFree86 tree..");
837	vsystem("chmod -R a+r /usr/X11R6");
838	vsystem("find /usr/X11R6 -type d | xargs chmod a+x");
839
840	/* Also do bogus minimal package registration so ports don't whine */
841	if (file_readable("/usr/X11R6/lib/X11/pkgreg.tar.gz")) {
842	    msgNotify("Installing package metainfo..");
843	    vsystem("tar xpzf /usr/X11R6/lib/X11/pkgreg.tar.gz -C / && rm /usr/X11R6/lib/X11/pkgreg.tar.gz");
844	}
845    }
846    return DITEM_SUCCESS;
847}
848
849/* Go newfs and/or mount all the filesystems we've been asked to */
850int
851installFilesystems(dialogMenuItem *self)
852{
853    int i;
854    Disk *disk;
855    Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev;
856    Device **devs;
857    PartInfo *root;
858    char dname[80];
859    extern int MakeDevChunk(Chunk *c, char *n);
860    Boolean upgrade = FALSE;
861
862    /* If we've already done this, bail out */
863    if (!variable_cmp(DISK_LABELLED, "written"))
864	return DITEM_SUCCESS;
865
866    upgrade = !variable_cmp(SYSTEM_STATE, "upgrade");
867    if (!checkLabels(TRUE, &rootdev, &swapdev, &usrdev, &vardev))
868	return DITEM_FAILURE;
869
870    if (rootdev)
871	root = (PartInfo *)rootdev->private_data;
872    else
873	root = NULL;
874
875    command_clear();
876    if (swapdev && RunningAsInit) {
877	/* As the very first thing, try to get ourselves some swap space */
878	sprintf(dname, "/dev/%s", swapdev->name);
879	if (!Fake && (!MakeDevChunk(swapdev, "/dev") || !file_readable(dname))) {
880	    msgConfirm("Unable to make device node for %s in /dev!\n"
881		       "The creation of filesystems will be aborted.", dname);
882	    return DITEM_FAILURE;
883	}
884
885	if (!Fake) {
886	    if (!swapon(dname))
887		msgNotify("Added %s as initial swap device", dname);
888	    else
889		msgConfirm("WARNING!  Unable to swap to %s: %s\n"
890			   "This may cause the installation to fail at some point\n"
891			   "if you don't have a lot of memory.", dname, strerror(errno));
892	}
893    }
894
895    if (rootdev && RunningAsInit) {
896	/* Next, create and/or mount the root device */
897	sprintf(dname, "/dev/r%s", rootdev->name);
898	if (!Fake && (!MakeDevChunk(rootdev, "/dev") || !file_readable(dname))) {
899	    msgConfirm("Unable to make device node for %s in /dev!\n"
900		       "The creation of filesystems will be aborted.", dname);
901	    return DITEM_FAILURE;
902	}
903	if (strcmp(root->mountpoint, "/"))
904	    msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", rootdev->name, root->mountpoint);
905
906	if (root->newfs && (!upgrade || !msgYesNo("You are upgrading - are you SURE you want to newfs the root partition?"))) {
907	    int i;
908
909	    msgNotify("Making a new root filesystem on %s", dname);
910	    i = vsystem("%s %s", root->newfs_cmd, dname);
911	    if (i) {
912		msgConfirm("Unable to make new root filesystem on %s!\n"
913			   "Command returned status %d", dname, i);
914		return DITEM_FAILURE;
915	    }
916	}
917	else {
918	    if (!upgrade) {
919		msgConfirm("Warning:  Using existing root partition.  It will be assumed\n"
920			   "that you have the appropriate device entries already in /dev.");
921	    }
922	    msgNotify("Checking integrity of existing %s filesystem.", dname);
923	    i = vsystem("fsck -y %s", dname);
924	    if (i)
925		msgConfirm("Warning: fsck returned status of %d for %s.\n"
926			   "This partition may be unsafe to use.", i, dname);
927	}
928
929	/* Switch to block device */
930	sprintf(dname, "/dev/%s", rootdev->name);
931	if (Mount("/mnt", dname)) {
932	    msgConfirm("Unable to mount the root file system on %s!  Giving up.", dname);
933	    return DITEM_FAILURE;
934	}
935    }
936
937    /* Now buzz through the rest of the partitions and mount them too */
938    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
939    for (i = 0; devs[i]; i++) {
940	if (!devs[i]->enabled)
941	    continue;
942
943	disk = (Disk *)devs[i]->private;
944	if (!disk->chunks) {
945	    msgConfirm("No chunk list found for %s!", disk->name);
946	    return DITEM_FAILURE;
947	}
948	if (RunningAsInit && root && (root->newfs || upgrade)) {
949	    Mkdir("/mnt/dev");
950	    if (!Fake)
951		MakeDevDisk(disk, "/mnt/dev");
952	}
953	else if (!RunningAsInit && !Fake)
954	    MakeDevDisk(disk, "/dev");
955
956	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
957	    if (c1->type == freebsd) {
958		for (c2 = c1->part; c2; c2 = c2->next) {
959		    if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) {
960			PartInfo *tmp = (PartInfo *)c2->private_data;
961
962			/* Already did root */
963			if (c2 == rootdev)
964			    continue;
965
966			if (tmp->newfs && (!upgrade || !msgYesNo("You are upgrading - are you SURE you want to newfs /dev/%s?", c2->name)))
967			    command_shell_add(tmp->mountpoint, "%s %s/dev/r%s", tmp->newfs_cmd, RunningAsInit ? "/mnt" : "", c2->name);
968			else
969			    command_shell_add(tmp->mountpoint, "fsck -y %s/dev/r%s", RunningAsInit ? "/mnt" : "", c2->name);
970			command_func_add(tmp->mountpoint, Mount, c2->name);
971		    }
972		    else if (c2->type == part && c2->subtype == FS_SWAP) {
973			char fname[80];
974			int i;
975
976			if (c2 == swapdev)
977			    continue;
978			sprintf(fname, "%s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name);
979			i = (Fake || swapon(fname));
980			if (!i)
981			    msgNotify("Added %s as an additional swap device", fname);
982			else
983			    msgConfirm("Unable to add %s as a swap device: %s", fname, strerror(errno));
984		    }
985		}
986	    }
987	    else if (c1->type == fat && c1->private_data && (root->newfs || upgrade)) {
988		char name[FILENAME_MAX];
989
990		sprintf(name, "%s/%s", RunningAsInit ? "/mnt" : "", ((PartInfo *)c1->private_data)->mountpoint);
991		Mkdir(name);
992	    }
993	}
994    }
995
996    if (RunningAsInit) {
997	msgNotify("Copying initial device files..");
998	/* Copy the boot floppy's dev files */
999	if ((root->newfs || upgrade) && vsystem("find -x /dev | cpio %s -pdum /mnt", cpioVerbosity())) {
1000	    msgConfirm("Couldn't clone the /dev files!");
1001	    return DITEM_FAILURE;
1002	}
1003    }
1004
1005    command_sort();
1006    command_execute();
1007    return DITEM_SUCCESS;
1008}
1009
1010static char *
1011getRelname(void)
1012{
1013    static char buf[64];
1014    int sz = (sizeof buf) - 1;
1015
1016    if (sysctlbyname("kern.osrelease", buf, &sz, NULL, 0) != -1) {
1017	buf[sz] = '\0';
1018	return buf;
1019    }
1020    else
1021	return "<unknown>";
1022}
1023
1024/* Initialize various user-settable values to their defaults */
1025int
1026installVarDefaults(dialogMenuItem *self)
1027{
1028    char *cp;
1029
1030    /* Set default startup options */
1031    variable_set2(VAR_RELNAME,			getRelname(), 0);
1032    variable_set2(VAR_CPIO_VERBOSITY,		"high", 0);
1033    variable_set2(VAR_KGET,			"YES", 0);
1034    variable_set2(VAR_TAPE_BLOCKSIZE,		DEFAULT_TAPE_BLOCKSIZE, 0);
1035    variable_set2(VAR_INSTALL_ROOT,		"/", 0);
1036    variable_set2(VAR_INSTALL_CFG,		"install.cfg", 0);
1037    variable_set2(VAR_TRY_DHCP,			"NO", 0);	/* For now */
1038    cp = getenv("EDITOR");
1039    if (!cp)
1040	cp = "/usr/bin/ee";
1041    variable_set2(VAR_EDITOR,			cp, 0);
1042    variable_set2(VAR_FTP_USER,			"ftp", 0);
1043    variable_set2(VAR_BROWSER_PACKAGE,		"lynx", 0);
1044    variable_set2(VAR_BROWSER_BINARY,		"/usr/local/bin/lynx", 0);
1045    variable_set2(VAR_FTP_STATE,		"passive", 0);
1046    variable_set2(VAR_NFS_SECURE,		"NO", -1);
1047    variable_set2(VAR_PKG_TMPDIR,		"/usr/tmp", 0);
1048    variable_set2(VAR_MEDIA_TIMEOUT,		itoa(MEDIA_TIMEOUT), 0);
1049    if (getpid() != 1)
1050	variable_set2(SYSTEM_STATE,		"update", 0);
1051    else
1052	variable_set2(SYSTEM_STATE,		"init", 0);
1053    variable_set2(VAR_NEWFS_ARGS,		"-b 8192 -f 1024", 0);
1054    return DITEM_SUCCESS;
1055}
1056
1057/* Load the environment up from various system configuration files */
1058void
1059installEnvironment(void)
1060{
1061    configEnvironmentRC_conf();
1062    if (file_readable("/etc/resolv.conf"))
1063	configEnvironmentResolv("/etc/resolv.conf");
1064}
1065
1066/* Copy the boot floppy contents into /stand */
1067Boolean
1068copySelf(void)
1069{
1070    int i;
1071
1072    if (file_readable("/boot.help"))
1073	vsystem("cp /boot.help /mnt");
1074    msgWeHaveOutput("Copying the boot floppy to /stand on root filesystem");
1075    i = vsystem("find -x /stand | cpio %s -pdum /mnt", cpioVerbosity());
1076    if (i) {
1077	msgConfirm("Copy returned error status of %d!", i);
1078	return FALSE;
1079    }
1080
1081    /* Copy the /etc files into their rightful place */
1082    if (vsystem("cd /mnt/stand; find etc | cpio %s -pdum /mnt", cpioVerbosity())) {
1083	msgConfirm("Couldn't copy up the /etc files!");
1084	return TRUE;
1085    }
1086    return TRUE;
1087}
1088
1089static void
1090create_termcap(void)
1091{
1092    FILE *fp;
1093
1094    const char *caps[] = {
1095	termcap_vt100, termcap_cons25, termcap_cons25_m, termcap_cons25r,
1096	termcap_cons25r_m, termcap_cons25l1, termcap_cons25l1_m, NULL,
1097    };
1098    const char **cp;
1099
1100    if (!file_readable(TERMCAP_FILE)) {
1101	Mkdir("/usr/share/misc");
1102	fp = fopen(TERMCAP_FILE, "w");
1103	if (!fp) {
1104	    msgConfirm("Unable to initialize termcap file. Some screen-oriented\nutilities may not work.");
1105	    return;
1106	}
1107	cp = caps;
1108	while (*cp)
1109	    fprintf(fp, "%s\n", *(cp++));
1110	fclose(fp);
1111    }
1112}
1113