install.c revision 87581
1139825Simp/*
245386Swpaul * The new sysinstall program.
345386Swpaul *
445386Swpaul * This is probably the last program in the `sysinstall' line - the next
545386Swpaul * generation being essentially a complete rewrite.
645386Swpaul *
745386Swpaul * $FreeBSD: head/usr.sbin/sade/install.c 87581 2001-12-09 23:40:02Z dillon $
845386Swpaul *
945386Swpaul * Copyright (c) 1995
1045386Swpaul *	Jordan Hubbard.  All rights reserved.
1145386Swpaul *
1245386Swpaul * Redistribution and use in source and binary forms, with or without
1345386Swpaul * modification, are permitted provided that the following conditions
1445386Swpaul * are met:
1545386Swpaul * 1. Redistributions of source code must retain the above copyright
1645386Swpaul *    notice, this list of conditions and the following disclaimer,
1745386Swpaul *    verbatim and that no modifications are made prior to this
1845386Swpaul *    point in the file.
1945386Swpaul * 2. Redistributions in binary form must reproduce the above copyright
2045386Swpaul *    notice, this list of conditions and the following disclaimer in the
2145386Swpaul *    documentation and/or other materials provided with the distribution.
2245386Swpaul *
2345386Swpaul * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
2445386Swpaul * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2545386Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2645386Swpaul * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
2745386Swpaul * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2845386Swpaul * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2945386Swpaul * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
3045386Swpaul * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3145386Swpaul * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3245386Swpaul * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3345386Swpaul * SUCH DAMAGE.
3445386Swpaul *
3545386Swpaul */
3645386Swpaul
37131652Sbms#include "sysinstall.h"
3845386Swpaul#include <ctype.h>
3945386Swpaul#include <sys/disklabel.h>
4045386Swpaul#include <sys/errno.h>
4145386Swpaul#include <sys/ioctl.h>
4245386Swpaul#include <sys/fcntl.h>
4345386Swpaul#include <sys/wait.h>
4445386Swpaul#include <sys/param.h>
4545386Swpaul#define MSDOSFS
4645386Swpaul#include <sys/mount.h>
4745386Swpaul#include <ufs/ufs/ufsmount.h>
4845386Swpaul#include <fs/msdosfs/msdosfsmount.h>
4945386Swpaul#undef MSDOSFS
5045386Swpaul#include <sys/stat.h>
5145386Swpaul#include <sys/sysctl.h>
5245386Swpaul#include <unistd.h>
5345386Swpaul#include <termios.h>
5445386Swpaul
5545386Swpaul/* Hack for rsaref package add, which displays interactive license.
5645386Swpaul * Used by package.c
5745386Swpaul */
5845386Swpaulint _interactiveHack;
5945386Swpaulint FixItMode = 0;
6045386Swpaul
6145386Swpaulstatic void	create_termcap(void);
6245386Swpaulstatic void	fixit_common(void);
6345386Swpaul
6445386Swpaul#define TERMCAP_FILE	"/usr/share/misc/termcap"
6545386Swpaul
6645386Swpaulstatic void	installConfigure(void);
6745386Swpaul
6845386SwpaulBoolean
6945386SwpaulcheckLabels(Boolean whinge, Chunk **rdev, Chunk **sdev, Chunk **udev, Chunk **vdev, Chunk **tdev, Chunk **hdev)
7045386Swpaul{
7145386Swpaul    Device **devs;
7245386Swpaul    Boolean status;
7345386Swpaul    Disk *disk;
7445386Swpaul    Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev, *tmpdev, *homedev;
7545386Swpaul    int i;
7645386Swpaul
7745386Swpaul    /* Don't allow whinging if noWarn is set */
7845386Swpaul    if (variable_get(VAR_NO_WARN))
79113038Sobrien	whinge = FALSE;
80113038Sobrien
81113038Sobrien    status = TRUE;
8298849Sken    if (rdev)
8398849Sken	*rdev = NULL;
8445386Swpaul    if (sdev)
8545386Swpaul	*sdev = NULL;
8645386Swpaul    if (udev)
8745386Swpaul	*udev = NULL;
8845386Swpaul    if (vdev)
8945386Swpaul	*vdev = NULL;
90129878Sphk    if (tdev)
9145386Swpaul	*tdev = NULL;
9245386Swpaul    if (hdev)
9398849Sken	*hdev = NULL;
9445386Swpaul    rootdev = swapdev = usrdev = vardev = tmpdev = homedev = NULL;
9545386Swpaul
9645386Swpaul    /* We don't need to worry about root/usr/swap if we're already multiuser */
9745386Swpaul    if (!RunningAsInit)
9845386Swpaul	return status;
9945386Swpaul
10083115Sbrooks    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
10183115Sbrooks    /* First verify that we have a root device */
10245386Swpaul    for (i = 0; devs[i]; i++) {
10345386Swpaul	if (!devs[i]->enabled)
10445386Swpaul	    continue;
10545386Swpaul	disk = (Disk *)devs[i]->private;
10645386Swpaul	msgDebug("Scanning disk %s for root filesystem\n", disk->name);
10745386Swpaul	if (!disk->chunks)
10845386Swpaul	    msgFatal("No chunk list found for %s!", disk->name);
109131655Sbms	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
110131655Sbms	    if (c1->type == freebsd) {
11145386Swpaul		for (c2 = c1->part; c2; c2 = c2->next) {
11249011Swpaul		    if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) {
11349011Swpaul			if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/")) {
11449011Swpaul			    if (rootdev) {
11545386Swpaul				if (whinge)
11698849Sken				    msgConfirm("WARNING:  You have more than one root device set?!\n"
11798849Sken					       "Using the first one found.");
11898849Sken				continue;
11998849Sken			    }
12098849Sken			    else {
12198849Sken				rootdev = c2;
122138424Salc				if (isDebug())
12398849Sken				    msgDebug("Found rootdev at %s!\n", rootdev->name);
12498849Sken			    }
12598849Sken			}
12698849Sken			else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/usr")) {
12798849Sken			    if (usrdev) {
12898849Sken				if (whinge)
12998849Sken				    msgConfirm("WARNING:  You have more than one /usr filesystem.\n"
13098849Sken					       "Using the first one found.");
13198849Sken				continue;
13298849Sken			    }
13398849Sken			    else {
13498849Sken				usrdev = c2;
13598849Sken				if (isDebug())
136119288Simp				    msgDebug("Found usrdev at %s!\n", usrdev->name);
137119288Simp			    }
13845386Swpaul			}
13998849Sken			else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/var")) {
14045386Swpaul			    if (vardev) {
14145386Swpaul				if (whinge)
14245386Swpaul				    msgConfirm("WARNING:  You have more than one /var filesystem.\n"
14345386Swpaul					       "Using the first one found.");
14458698Sjlemon				continue;
14598849Sken			    }
14698849Sken			    else {
14798849Sken				vardev = c2;
14898849Sken				if (isDebug())
14998849Sken				    msgDebug("Found vardev at %s!\n", vardev->name);
15098849Sken			    }
15198849Sken			} else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/tmp")) {
15245386Swpaul			    if (tmpdev) {
15398849Sken				if (whinge)
15498849Sken				    msgConfirm("WARNING:  You have more than one /tmp filesystem.\n"
15598849Sken					       "Using the first one found.");
15698849Sken				continue;
15798849Sken			    }
15898849Sken			    else {
15998849Sken				tmpdev = c2;
16098849Sken				if (isDebug())
16145386Swpaul				    msgDebug("Found tmpdev at %s!\n", tmpdev->name);
16245386Swpaul			    }
16345386Swpaul			} else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/home")) {
16445386Swpaul			    if (homedev) {
16545386Swpaul				if (whinge)
16645386Swpaul				    msgConfirm("WARNING:  You have more than one /home filesystem.\n"
16763702Swpaul					       "Using the first one found.");
16863699Swpaul				continue;
16963702Swpaul			    }
17045386Swpaul			    else {
17145386Swpaul				homedev = c2;
17245386Swpaul				if (isDebug())
17364139Swpaul				    msgDebug("Found homedev at %s!\n", homedev->name);
17464139Swpaul			    }
17564139Swpaul			}
17645386Swpaul		    }
17745386Swpaul		}
17856206Swpaul	    }
17956206Swpaul	}
18045386Swpaul    }
18145386Swpaul
18245386Swpaul    /* Now check for swap devices */
18398849Sken    for (i = 0; devs[i]; i++) {
18498849Sken	if (!devs[i]->enabled)
18598849Sken	    continue;
18698849Sken	disk = (Disk *)devs[i]->private;
18798849Sken	msgDebug("Scanning disk %s for swap partitions\n", disk->name);
18898849Sken	if (!disk->chunks)
189126080Sphk	    msgFatal("No chunk list found for %s!", disk->name);
190126080Sphk	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
191111815Sphk	    if (c1->type == freebsd) {
192111815Sphk		for (c2 = c1->part; c2; c2 = c2->next) {
193111815Sphk		    if (c2->type == part && c2->subtype == FS_SWAP && !swapdev) {
194111815Sphk			swapdev = c2;
19598849Sken			if (isDebug())
19698849Sken			    msgDebug("Found swapdev at %s!\n", swapdev->name);
197142407Simp			break;
198142407Simp		    }
199142407Simp		}
200142407Simp	    }
201142407Simp	}
20245386Swpaul    }
203142407Simp
204142407Simp    /* Copy our values over */
20545386Swpaul    if (rdev)
206142407Simp	*rdev = rootdev;
207142407Simp    if (sdev)
208142407Simp	*sdev = swapdev;
209142407Simp    if (udev)
210142407Simp	*udev = usrdev;
211142407Simp    if (vdev)
212142407Simp	*vdev = vardev;
213142407Simp    if (tdev)
214142407Simp	*tdev = tmpdev;
215142407Simp    if (hdev)
21645386Swpaul	*hdev = homedev;
217142407Simp
218142407Simp    if (!rootdev && whinge) {
219142407Simp	msgConfirm("No root device found - you must label a partition as /\n"
22045386Swpaul		   "in the label editor.");
221142407Simp	status = FALSE;
222142407Simp    }
223142407Simp    if (!swapdev && whinge) {
22445386Swpaul	msgConfirm("No swap devices found - you must create at least one\n"
225142407Simp		   "swap partition.");
226142407Simp	status = FALSE;
227142407Simp    }
228142407Simp    return status;
229142407Simp}
230142407Simp
231142407Simpstatic int
232142407SimpinstallInitial(void)
233142407Simp{
23498849Sken    static Boolean alreadyDone = FALSE;
235142407Simp    int status = DITEM_SUCCESS;
236142407Simp
237142407Simp    if (alreadyDone)
23898849Sken	return DITEM_SUCCESS;
239142407Simp
240142407Simp    if (!variable_get(DISK_LABELLED)) {
241142407Simp	msgConfirm("You need to assign disk labels before you can proceed with\n"
242142407Simp		   "the installation.");
243142407Simp	return DITEM_FAILURE;
244142407Simp    }
245142407Simp    /* If it's labelled, assume it's also partitioned */
246142407Simp    if (!variable_get(DISK_PARTITIONED))
247142407Simp	variable_set2(DISK_PARTITIONED, "yes", 0);
248142407Simp
249142407Simp    /* If we refuse to proceed, bail. */
25045386Swpaul    dialog_clear_norefresh();
251142407Simp    if (!variable_get(VAR_NO_WARN)) {
252142407Simp	if (msgYesNo(
253142407Simp	    "Last Chance!  Are you SURE you want continue the installation?\n\n"
25445386Swpaul	    "If you're running this on a disk with data you wish to save\n"
25598849Sken	    "then WE STRONGLY ENCOURAGE YOU TO MAKE PROPER BACKUPS before\n"
25699013Speter	    "proceeding!\n\n"
25799013Speter	    "We can take no responsibility for lost disk contents!") != 0)
25898849Sken	return DITEM_FAILURE;
25998849Sken    }
26049011Swpaul
26149011Swpaul    if (DITEM_STATUS(diskLabelCommit(NULL)) != DITEM_SUCCESS) {
26249011Swpaul	msgConfirm("Couldn't make filesystems properly.  Aborting.");
26349011Swpaul	return DITEM_FAILURE;
26449011Swpaul    }
26549011Swpaul
26649011Swpaul    if (!copySelf()) {
26749011Swpaul	msgConfirm("installInitial: Couldn't clone the boot floppy onto the\n"
26849011Swpaul		   "root file system.  Aborting!");
26949011Swpaul	return DITEM_FAILURE;
27051455Swpaul    }
27149011Swpaul
27249011Swpaul    if (!Restarting && chroot("/mnt") == -1) {
27349011Swpaul	msgConfirm("installInitial: Unable to chroot to %s - this is bad!",
27449011Swpaul		   "/mnt");
27549011Swpaul	return DITEM_FAILURE;
27649011Swpaul    }
277113506Smdodd
278113506Smdodd    chdir("/");
279113506Smdodd    variable_set2(RUNNING_ON_ROOT, "yes", 0);
28049011Swpaul
28145386Swpaul    /* Configure various files in /etc */
28245386Swpaul    if (DITEM_STATUS(configResolv(NULL)) == DITEM_FAILURE)
28345386Swpaul	status = DITEM_FAILURE;
28445386Swpaul    if (DITEM_STATUS(configFstab(NULL)) == DITEM_FAILURE)
28545386Swpaul	status = DITEM_FAILURE;
28645386Swpaul
28745386Swpaul    /* stick a helpful shell over on the 4th VTY */
28845386Swpaul    if (!variable_get(VAR_NO_HOLOSHELL))
28945386Swpaul	systemCreateHoloshell();
29045386Swpaul
29145386Swpaul    alreadyDone = TRUE;
29245386Swpaul    return status;
29345386Swpaul}
29445386Swpaul
29545386Swpaulint
29645386SwpaulinstallFixitHoloShell(dialogMenuItem *self)
29745386Swpaul{
29845386Swpaul    FixItMode = 1;
29945386Swpaul    systemCreateHoloshell();
30045386Swpaul    return DITEM_SUCCESS;
30145386Swpaul    FixItMode = 0;
30245386Swpaul}
30345386Swpaul
30445386Swpaulint
30545386SwpaulinstallFixitCDROM(dialogMenuItem *self)
30645386Swpaul{
30745386Swpaul    struct stat sb;
30845386Swpaul
30945386Swpaul    if (!RunningAsInit)
31045386Swpaul	return DITEM_SUCCESS;
31145386Swpaul
31245386Swpaul    variable_set2(SYSTEM_STATE, "fixit", 0);
31345386Swpaul    (void)unlink("/mnt2");
31445386Swpaul    (void)rmdir("/mnt2");
31545386Swpaul
31645386Swpaul    while (1) {
31745386Swpaul	msgConfirm("Please insert a FreeBSD live filesystem CD/DVD and press return");
31845386Swpaul	if (DITEM_STATUS(mediaSetCDROM(NULL)) != DITEM_SUCCESS
31945386Swpaul	    || !DEVICE_INIT(mediaDevice)) {
32045386Swpaul	    /* If we can't initialize it, it's probably not a FreeBSD CDROM so punt on it */
32145386Swpaul	    mediaClose();
322131654Sbms	    if (msgYesNo("Unable to mount the disc - do you want to try again?") != 0)
32345386Swpaul		return DITEM_FAILURE;
32445386Swpaul	}
32545386Swpaul	else
32645386Swpaul	    break;
32745386Swpaul    }
32845386Swpaul
32945386Swpaul    /* Since the fixit code expects everything to be in /mnt2, and the CDROM mounting stuff /dist, do
33045386Swpaul     * a little kludge dance here..
33145386Swpaul     */
33245386Swpaul    if (symlink("/dist", "/mnt2")) {
33345386Swpaul	msgConfirm("Unable to symlink /mnt2 to the disc mount point.  Please report this\n"
33445386Swpaul		   "unexpected failure to freebsd-bugs@FreeBSD.org.");
33545386Swpaul	return DITEM_FAILURE;
33645386Swpaul    }
33745386Swpaul
33845386Swpaul    /*
33945386Swpaul     * If /tmp points to /mnt2/tmp from a previous fixit floppy session, it's
34045386Swpaul     * not very good for us if we point it to the CDROM now.  Rather make it
34145386Swpaul     * a directory in the root MFS then.  Experienced admins will still be
34245386Swpaul     * able to mount their disk's /tmp over this if they need.
34345386Swpaul     */
34445386Swpaul    if (lstat("/tmp", &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFLNK)
34545386Swpaul	(void)unlink("/tmp");
346131654Sbms    Mkdir("/tmp");
34745386Swpaul
34845386Swpaul    /*
34945386Swpaul     * Since setuid binaries ignore LD_LIBRARY_PATH, we indeed need the
35045386Swpaul     * ld.so.hints file.  Fortunately, it's fairly small (~ 3 KB).
35145386Swpaul     */
35245386Swpaul    if (!file_readable("/var/run/ld.so.hints")) {
35345386Swpaul	Mkdir("/var/run");
35445386Swpaul	if (vsystem("/mnt2/sbin/ldconfig -s /mnt2/usr/lib")) {
355131654Sbms	    msgConfirm("Warning: ldconfig could not create the ld.so hints file.\n"
35645386Swpaul		       "Dynamic executables from the disc likely won't work.");
35745386Swpaul	}
35845386Swpaul    }
35945386Swpaul
36045386Swpaul    /* Yet more iggly hardcoded pathnames. */
36145386Swpaul    Mkdir("/usr/libexec");
36245386Swpaul    if (!file_readable("/usr/libexec/ld.so") && file_readable("/mnt2/usr/libexec/ld.so")) {
363131654Sbms	if (symlink("/mnt2/usr/libexec/ld.so", "/usr/libexec/ld.so"))
36445386Swpaul	    msgDebug("Couldn't link to ld.so - not necessarily a problem for ELF\n");
36545386Swpaul    }
36645386Swpaul    if (!file_readable("/usr/libexec/ld-elf.so.1")) {
36745386Swpaul	if (symlink("/mnt2/usr/libexec/ld-elf.so.1", "/usr/libexec/ld-elf.so.1")) {
36845386Swpaul	    msgConfirm("Warning: could not create the symlink for ld-elf.so.1\n"
36945386Swpaul		       "Dynamic executables from the disc likely won't work.");
37045386Swpaul	}
37145386Swpaul    }
37245386Swpaul    /* optional nicety */
37345386Swpaul    if (!file_readable("/usr/bin/vi"))
374131654Sbms	symlink("/mnt2/usr/bin/vi", "/usr/bin/vi");
37545386Swpaul    fixit_common();
37645386Swpaul    mediaClose();
37745386Swpaul    msgConfirm("Please remove the FreeBSD fixit CDROM now.");
37845386Swpaul    return DITEM_SUCCESS;
37945386Swpaul}
38045386Swpaul
38145386Swpaulint
38245386SwpaulinstallFixitFloppy(dialogMenuItem *self)
38345386Swpaul{
38445386Swpaul    struct ufs_args args;
38545386Swpaul    extern char *distWanted;
38645386Swpaul
38745386Swpaul    if (!RunningAsInit)
38845386Swpaul	return DITEM_SUCCESS;
38945386Swpaul
39045386Swpaul    /* Try to open the floppy drive */
39145386Swpaul    if (DITEM_STATUS(mediaSetFloppy(NULL)) == DITEM_FAILURE || !mediaDevice) {
39245386Swpaul	msgConfirm("Unable to set media device to floppy.");
39345386Swpaul	mediaClose();
39445386Swpaul	return DITEM_FAILURE;
39545386Swpaul    }
39645386Swpaul
39745386Swpaul    memset(&args, 0, sizeof(args));
398131654Sbms    args.fspec = mediaDevice->devname;
39945386Swpaul    mediaDevice->private = "/mnt2";
40045386Swpaul    distWanted = NULL;
40145386Swpaul    Mkdir("/mnt2");
40245386Swpaul
40345386Swpaul    variable_set2(SYSTEM_STATE, "fixit", 0);
404102336Salfred
405102336Salfred    while (1) {
40645386Swpaul	if (!DEVICE_INIT(mediaDevice)) {
40745386Swpaul	    if (msgYesNo("The attempt to mount the fixit floppy failed, bad floppy\n"
40845386Swpaul			 "or unclean filesystem.  Do you want to try again?"))
40945386Swpaul		return DITEM_FAILURE;
41045386Swpaul	}
41145386Swpaul	else
41245386Swpaul	    break;
41345386Swpaul    }
41445386Swpaul    if (!directory_exists("/tmp"))
41545386Swpaul	(void)symlink("/mnt2/tmp", "/tmp");
41645386Swpaul    fixit_common();
41745386Swpaul    mediaClose();
41845386Swpaul    msgConfirm("Please remove the fixit floppy now.");
41945386Swpaul    return DITEM_SUCCESS;
42045386Swpaul}
421131654Sbms
42245386Swpaul/*
42345386Swpaul * The common code for both fixit variants.
42445386Swpaul */
42545386Swpaulstatic void
42645386Swpaulfixit_common(void)
42745386Swpaul{
428102336Salfred    pid_t child;
429102336Salfred    int waitstatus;
43045386Swpaul
43145386Swpaul    if (!directory_exists("/var/tmp/vi.recover")) {
43245386Swpaul	if (DITEM_STATUS(Mkdir("/var/tmp/vi.recover")) != DITEM_SUCCESS) {
43345386Swpaul	    msgConfirm("Warning:  Was unable to create a /var/tmp/vi.recover directory.\n"
43445386Swpaul		       "vi will kvetch and moan about it as a result but should still\n"
43545386Swpaul		       "be essentially usable.");
43645386Swpaul	}
43745386Swpaul    }
43845386Swpaul    if (!directory_exists("/bin"))
43949133Swpaul	(void)Mkdir("/bin");
44045386Swpaul    (void)symlink("/stand/sh", "/bin/sh");
44145386Swpaul    /* Link the /etc/ files */
442131654Sbms    if (DITEM_STATUS(Mkdir("/etc")) != DITEM_SUCCESS)
44345386Swpaul	msgConfirm("Unable to create an /etc directory!  Things are weird on this floppy..");
44445386Swpaul    else if ((symlink("/mnt2/etc/spwd.db", "/etc/spwd.db") == -1 && errno != EEXIST) ||
44545386Swpaul	     (symlink("/mnt2/etc/protocols", "/etc/protocols") == -1 && errno != EEXIST) ||
44645386Swpaul	     (symlink("/mnt2/etc/services", "/etc/services") == -1 && errno != EEXIST))
44745386Swpaul	msgConfirm("Couldn't symlink the /etc/ files!  I'm not sure I like this..");
44845386Swpaul    if (!file_readable(TERMCAP_FILE))
44945386Swpaul	create_termcap();
45045386Swpaul    if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0)
45145386Swpaul	systemSuspendDialog();	/* must be before the fork() */
45245386Swpaul    if (!(child = fork())) {
45345386Swpaul	int i, fd;
45445386Swpaul	struct termios foo;
45545386Swpaul	extern int login_tty(int);
45645386Swpaul
45745386Swpaul	ioctl(0, TIOCNOTTY, NULL);
45845386Swpaul	for (i = getdtablesize(); i >= 0; --i)
45945386Swpaul	    close(i);
46045386Swpaul
46198849Sken	if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0)
46298849Sken	    fd = open("/dev/console", O_RDWR);
46398849Sken	else
46498849Sken	    fd = open("/dev/ttyv3", O_RDWR);
46598849Sken	ioctl(0, TIOCSCTTY, &fd);
46698849Sken	dup2(0, 1);
46798849Sken	dup2(0, 2);
46898849Sken	DebugFD = 2;
46998849Sken	if (login_tty(fd) == -1)
47098849Sken	    msgDebug("fixit: I can't set the controlling terminal.\n");
47198849Sken
47298849Sken	signal(SIGTTOU, SIG_IGN);
47398849Sken	if (tcgetattr(0, &foo) != -1) {
47498849Sken	    foo.c_cc[VERASE] = '\010';
47598849Sken	    if (tcsetattr(0, TCSANOW, &foo) == -1)
47698849Sken		msgDebug("fixit shell: Unable to set erase character.\n");
47798849Sken	}
47898849Sken	else
47998849Sken	    msgDebug("fixit shell: Unable to get terminal attributes!\n");
48098849Sken	setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/stand:"
48198849Sken	       "/mnt2/stand:/mnt2/bin:/mnt2/sbin:/mnt2/usr/bin:/mnt2/usr/sbin", 1);
48298849Sken	setenv("MAKEDEVPATH", "/sbin:/bin:/stand:"
48398849Sken	       "/mnt2/sbin:/mnt2/bin:/mnt2/stand", 1);
48498849Sken	if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) {
485131654Sbms	    printf("Waiting for fixit shell to exit.\n"
48698849Sken		"When you are done, type ``exit'' to exit\n"
48798849Sken		"the fixit shell and be returned here.\n\n");
48898849Sken	    fflush(stdout);
48998849Sken	}
49098849Sken
49198849Sken	/* use the .profile from the fixit medium */
49298849Sken	setenv("HOME", "/mnt2", 1);
49398849Sken	chdir("/mnt2");
49498849Sken	execlp("sh", "-sh", (char *)0);
49598849Sken	msgDebug("fixit shell: Failed to execute shell!\n");
49698849Sken	_exit(1);;
49798849Sken    }
49898849Sken    else {
49998849Sken	if (strcmp(variable_get(VAR_FIXIT_TTY), "standard") == 0) {
50098849Sken	    dialog_clear_norefresh();
50198849Sken	    msgNotify("Waiting for fixit shell to exit.  Go to VTY4 now by\n"
50298849Sken		"typing ALT-F4.  When you are done, type ``exit'' to exit\n"
50398849Sken		"the fixit shell and be returned here\n.");
50498849Sken	}
50598849Sken	(void)waitpid(child, &waitstatus, 0);
50698849Sken	if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0)
50798849Sken	    systemResumeDialog();
50898849Sken    }
50998849Sken    dialog_clear();
51098849Sken}
51198849Sken
51298849Sken
51398849Skenint
51498849SkeninstallExpress(dialogMenuItem *self)
51598849Sken{
51698849Sken    int i;
51798849Sken
51898849Sken    dialog_clear_norefresh();
51998849Sken    variable_set2(SYSTEM_STATE, "express", 0);
52098849Sken#ifndef __alpha__
52198849Sken    if (DITEM_STATUS((i = diskPartitionEditor(self))) == DITEM_FAILURE)
52298849Sken	return i;
523131654Sbms#endif
52498849Sken
52598849Sken    if (DITEM_STATUS((i = diskLabelEditor(self))) == DITEM_FAILURE)
52698849Sken	return i;
52798849Sken
52898849Sken    if (DITEM_STATUS((i = installCommit(self))) == DITEM_SUCCESS) {
52998849Sken	i |= DITEM_LEAVE_MENU;
53098849Sken	/* Set default security level */
53198849Sken	configSecurityModerate(NULL);
53298849Sken
53398849Sken	/* Give user the option of one last configuration spree */
53498849Sken	installConfigure();
53598849Sken    }
53698849Sken    return i;
53798849Sken}
53898849Sken
53998849Sken/* Standard mode installation */
54098849Skenint
54198849SkeninstallStandard(dialogMenuItem *self)
54298849Sken{
54398849Sken    int i, tries = 0;
54498849Sken    Device **devs;
54598849Sken
54698849Sken    variable_set2(SYSTEM_STATE, "standard", 0);
54798849Sken    dialog_clear_norefresh();
54898849Sken#ifndef __alpha__
54998849Sken    msgConfirm("In the next menu, you will need to set up a DOS-style (\"fdisk\") partitioning\n"
55098849Sken	       "scheme for your hard disk.  If you simply wish to devote all disk space\n"
55198849Sken	       "to FreeBSD (overwriting anything else that might be on the disk(s) selected)\n"
55298849Sken	       "then use the (A)ll command to select the default partitioning scheme followed\n"
55398849Sken	       "by a (Q)uit.  If you wish to allocate only free space to FreeBSD, move to a\n"
55498849Sken	       "partition marked \"unused\" and use the (C)reate command.");
55598849Sken
55698849Skennodisks:
55798849Sken    if (DITEM_STATUS(diskPartitionEditor(self)) == DITEM_FAILURE)
55898849Sken	return DITEM_FAILURE;
55998849Sken
56098849Sken    if (diskGetSelectCount(&devs) <= 0 && tries < 3) {
56198849Sken	msgConfirm("You need to select some disks to operate on!  Be sure to use SPACE\n"
56298849Sken		   "instead of RETURN in the disk selection menu when selecting a disk.");
56398849Sken	++tries;
56498849Sken	goto nodisks;
56598849Sken    }
56698849Sken#endif
56798849Sken
56898849Sken#ifdef __alpha__
56998849Sken    msgConfirm("Now you need to create BSD partitions on the disk which you are\n"
57098849Sken	       "installing to.  If you have a reasonable amount of disk space (200MB or more)\n"
57198849Sken	       "and don't have any special requirements, simply use the (A)uto command to\n"
57298849Sken	       "allocate space automatically.  If you have more specific needs or just don't\n"
57398849Sken	       "care for the layout chosen by (A)uto, press F1 for more information on\n"
57498849Sken	       "manual layout.");
57598849Sken#else
57698849Sken    msgConfirm("Now you need to create BSD partitions inside of the fdisk partition(s)\n"
57798849Sken	       "just created.  If you have a reasonable amount of disk space (200MB or more)\n"
57898849Sken	       "and don't have any special requirements, simply use the (A)uto command to\n"
57998849Sken	       "allocate space automatically.  If you have more specific needs or just don't\n"
58098849Sken	       "care for the layout chosen by (A)uto, press F1 for more information on\n"
58198849Sken	       "manual layout.");
58298849Sken#endif
58398849Sken
58498849Sken    if (DITEM_STATUS(diskLabelEditor(self)) == DITEM_FAILURE)
58598849Sken	return DITEM_FAILURE;
58698849Sken
58798849Sken    if (DITEM_STATUS((i = installCommit(self))) == DITEM_FAILURE) {
58898849Sken	dialog_clear();
58998849Sken	msgConfirm("Installation completed with some errors.  You may wish to\n"
59098849Sken		   "scroll through the debugging messages on VTY1 with the\n"
59198849Sken		   "scroll-lock feature.  You can also choose \"No\" at the next\n"
59298849Sken		   "prompt and go back into the installation menus to try and retry\n"
59398849Sken		   "whichever operations have failed.");
59498849Sken	return i;
59598849Sken
59698849Sken    }
59798849Sken    else {
59898849Sken	dialog_clear();
59998849Sken	msgConfirm("Congratulations!  You now have FreeBSD installed on your system.\n\n"
60098849Sken		   "We will now move on to the final configuration questions.\n"
60198849Sken		   "For any option you do not wish to configure, simply select\n"
60298849Sken		   "No.\n\n"
60398849Sken		   "If you wish to re-enter this utility after the system is up, you\n"
60498849Sken		   "may do so by typing: /usr/sbin/sysinstall.");
60598849Sken    }
60698849Sken    if (mediaDevice->type != DEVICE_TYPE_FTP && mediaDevice->type != DEVICE_TYPE_NFS) {
60798849Sken	if (!msgYesNo("Would you like to configure any Ethernet or SLIP/PPP network devices?")) {
60898849Sken	    Device *tmp = tcpDeviceSelect();
60998849Sken
61098849Sken	    if (tmp && !((DevInfo *)tmp->private)->use_dhcp && !msgYesNo("Would you like to bring the %s interface up right now?", tmp->name))
61198849Sken		if (!DEVICE_INIT(tmp))
61298849Sken		    msgConfirm("Initialization of %s device failed.", tmp->name);
61398849Sken	}
61498849Sken	dialog_clear_norefresh();
61598849Sken    }
61698849Sken
61798849Sken    if (!msgNoYes("Do you want this machine to function as a network gateway?"))
61898849Sken	variable_set2("gateway_enable", "YES", 1);
61998849Sken
62098849Sken    dialog_clear_norefresh();
62198849Sken    if (!msgNoYes("Do you want to configure inetd and the network services that it provides?"))
62298849Sken        configInetd(self);
62398849Sken
62498849Sken    dialog_clear_norefresh();
62598849Sken    if (!msgNoYes("Do you want to have anonymous FTP access to this machine?"))
62698849Sken	configAnonFTP(self);
62798849Sken
62898849Sken    dialog_clear_norefresh();
62998849Sken    if (!msgNoYes("Do you want to configure this machine as an NFS server?"))
63098849Sken	configNFSServer(self);
63198849Sken
63298849Sken    dialog_clear_norefresh();
63398849Sken    if (!msgNoYes("Do you want to configure this machine as an NFS client?"))
63498849Sken	variable_set2("nfs_client_enable", "YES", 1);
63598849Sken
63698849Sken    if (!msgNoYes("Do you want to select a default security profile for\n"
63798849Sken	         "this host (select No for \"moderate\" security)?"))
63898849Sken	configSecurityProfile(self);
63998849Sken    else
64098849Sken	configSecurityModerate(self);
64198849Sken
64298849Sken    dialog_clear_norefresh();
64398849Sken    if (!msgNoYes("Would you like to customize your system console settings?"))
64498849Sken	dmenuOpenSimple(&MenuSyscons, FALSE);
64598849Sken
64698849Sken    dialog_clear_norefresh();
64798849Sken    if (!msgYesNo("Would you like to set this machine's time zone now?"))
64898849Sken	systemExecute("tzsetup");
64998849Sken
65098849Sken#ifdef __i386__
65198849Sken    dialog_clear_norefresh();
65298849Sken    if (!msgYesNo("Would you like to enable Linux binary compatibility?"))
653131654Sbms	(void)configLinux(self);
65498849Sken#endif
65598849Sken
65698849Sken    dialog_clear_norefresh();
65798849Sken    if (msgNoYes("Does this system have a USB mouse attached to it?"))
65898849Sken	dmenuOpenSimple(&MenuMouse, FALSE);
65998849Sken
66098849Sken    /* Now would be a good time to checkpoint the configuration data */
66198849Sken    configRC_conf();
66298849Sken    sync();
66398849Sken
66498849Sken    if (directory_exists("/usr/X11R6")) {
66598849Sken	dialog_clear_norefresh();
66698849Sken	if (!msgYesNo("Would you like to configure your X server at this time?"))
66798849Sken	    (void)configXSetup(self);
66898849Sken    }
66998849Sken
67098849Sken    dialog_clear_norefresh();
67198849Sken    if (!msgYesNo("The FreeBSD package collection is a collection of thousands of ready-to-run\n"
67298849Sken		  "applications, from text editors to games to WEB servers and more.  Would you\n"
67398849Sken		  "like to browse the collection now?")) {
67498849Sken	(void)configPackages(self);
67598849Sken    }
676131654Sbms
67798849Sken    if (!msgYesNo("Would you like to add any initial user accounts to the system?\n"
67898849Sken		  "Adding at least one account for yourself at this stage is suggested\n"
67998849Sken		  "since working as the \"root\" user is dangerous (it is easy to do\n"
68098849Sken		  "things which adversely affect the entire system)."))
68198849Sken	(void)configUsers(self);
682131654Sbms
68398849Sken    msgConfirm("Now you must set the system manager's password.\n"
68498849Sken	       "This is the password you'll use to log in as \"root\".");
68598849Sken    if (!systemExecute("passwd root"))
68698849Sken	variable_set2("root_password", "YES", 0);
68798849Sken
68898849Sken    /* XXX Put whatever other nice configuration questions you'd like to ask the user here XXX */
68998849Sken
69098849Sken    /* Give user the option of one last configuration spree */
69198849Sken    dialog_clear_norefresh();
69298849Sken    installConfigure();
69398849Sken    return DITEM_LEAVE_MENU;
69498849Sken}
69598849Sken
69698849Sken/* The version of commit we call from the Install Custom menu */
69798849Skenint
69898849SkeninstallCustomCommit(dialogMenuItem *self)
69998849Sken{
70098849Sken    int i;
70198849Sken
70298849Sken    i = installCommit(self);
70398849Sken    if (DITEM_STATUS(i) == DITEM_SUCCESS) {
70498849Sken	/* Set default security level */
70598849Sken	configSecurityModerate(NULL);
70698849Sken
707131652Sbms	/* Give user the option of one last configuration spree */
70898849Sken	installConfigure();
70998849Sken	return i;
71098849Sken    }
71198849Sken    else
71298849Sken	msgConfirm("The commit operation completed with errors.  Not\n"
71398849Sken		   "updating /etc files.");
71498849Sken    return i;
71598849Sken}
71698849Sken
71798849Sken/*
71898849Sken * What happens when we finally decide to going ahead with the installation.
71998849Sken *
72098849Sken * This is broken into multiple stages so that the user can do a full
72198849Sken * installation but come back here again to load more distributions,
72298849Sken * perhaps from a different media type.  This would allow, for
72398849Sken * example, the user to load the majority of the system from CDROM and
72498849Sken * then use ftp to load just the CRYPTO dist.
72598849Sken */
72698849Skenint
72798849SkeninstallCommit(dialogMenuItem *self)
72898849Sken{
72998849Sken    int i;
73098849Sken    char *str;
73198849Sken
73298849Sken    dialog_clear_norefresh();
73398849Sken    if (!Dists)
73498849Sken	distConfig(NULL);
73598849Sken
73698849Sken    if (!Dists) {
73798849Sken	(void)dmenuOpenSimple(&MenuDistributions, FALSE);
73898849Sken	/* select reasonable defaults if necessary */
73998849Sken	if (!Dists)
74098849Sken	    Dists = _DIST_USER;
74198849Sken    }
74298849Sken
74398849Sken    if (!mediaVerify())
74498849Sken	return DITEM_FAILURE;
74598849Sken
74698849Sken    str = variable_get(SYSTEM_STATE);
74798849Sken    if (isDebug())
74898849Sken	msgDebug("installCommit: System state is `%s'\n", str);
74998849Sken
75098849Sken    /* Installation stuff we wouldn't do to a running system */
75198849Sken    if (RunningAsInit && DITEM_STATUS((i = installInitial())) == DITEM_FAILURE)
75298849Sken	return i;
753131654Sbms
75498849Skentry_media:
75598849Sken    if (!DEVICE_INIT(mediaDevice)) {
75698849Sken	if (!msgYesNo("Unable to initialize selected media. Would you like to\n"
75798849Sken		      "adjust your media configuration and try again?")) {
75898849Sken	    mediaDevice = NULL;
75998849Sken	    if (!mediaVerify())
76098849Sken		return DITEM_FAILURE;
76198849Sken	    else
76298849Sken		goto try_media;
76398849Sken	}
76498849Sken	else
76598849Sken	    return DITEM_FAILURE;
76698849Sken    }
76798849Sken
768106627Sjhb    /* Now go get it all */
76998849Sken    i = distExtractAll(self);
770131654Sbms
77198849Sken    /* When running as init, *now* it's safe to grab the rc.foo vars */
77298849Sken    installEnvironment();
77398849Sken
77498849Sken    variable_set2(SYSTEM_STATE, DITEM_STATUS(i) == DITEM_FAILURE ? "error-install" : "full-install", 0);
77598849Sken
77698849Sken    return i;
77798849Sken}
77898849Sken
77998849Skenstatic void
78098849SkeninstallConfigure(void)
78198849Sken{
78298849Sken    /* Final menu of last resort */
78398849Sken    if (!msgNoYes("Visit the general configuration menu for a chance to set\n"
78498849Sken		  "any last options?"))
78598849Sken	dmenuOpenSimple(&MenuConfigure, FALSE);
78698849Sken    configRC_conf();
78798849Sken    sync();
78898849Sken}
78998849Sken
790131654Sbmsint
79198849SkeninstallFixupBin(dialogMenuItem *self)
79298849Sken{
79345386Swpaul    Device **devs;
79445386Swpaul    char *cp;
79545386Swpaul    int i;
79645386Swpaul    FILE *fp;
79745386Swpaul    int kstat = 1;
798102336Salfred
799102336Salfred    /* All of this is done only as init, just to be safe */
80045386Swpaul    if (RunningAsInit) {
80145386Swpaul#ifdef __i386__
802131654Sbms	if ((fp = fopen("/boot/loader.conf", "a")) != NULL) {
80345386Swpaul	    if (!kstat || !OnVTY)
80445386Swpaul		fprintf(fp, "# -- sysinstall generated deltas -- #\n");
80545386Swpaul	    if (!kstat)
80645386Swpaul		fprintf(fp, "userconfig_script_load=\"YES\"\n");
80745386Swpaul	    if (!OnVTY)
80845386Swpaul		fprintf(fp, "console=\"comconsole\"\n");
80945386Swpaul	    fclose(fp);
81045386Swpaul	}
81145386Swpaul#endif
81245386Swpaul	/* BOGON #1: Resurrect /dev after bin distribution screws it up */
81345386Swpaul	dialog_clear_norefresh();
81445386Swpaul	msgNotify("Remaking all devices.. Please wait!");
81545386Swpaul	if (vsystem("cd /dev; sh MAKEDEV all")) {
81645386Swpaul	    msgConfirm("MAKEDEV returned non-zero status");
81745386Swpaul	    return DITEM_FAILURE | DITEM_RESTORE;
81845386Swpaul	}
81945386Swpaul
82045386Swpaul	dialog_clear_norefresh();
82145386Swpaul	msgNotify("Resurrecting /dev entries for slices..");
82245386Swpaul	devs = deviceFind(NULL, DEVICE_TYPE_DISK);
82345386Swpaul	if (!devs)
82445386Swpaul	    msgFatal("Couldn't get a disk device list!");
82545386Swpaul
82645386Swpaul	/* Resurrect the slices that the former clobbered */
82745386Swpaul	for (i = 0; devs[i]; i++) {
82845386Swpaul	    Disk *disk = (Disk *)devs[i]->private;
82945386Swpaul	    Chunk *c1;
83045386Swpaul
83145386Swpaul	    if (!devs[i]->enabled)
83245386Swpaul		continue;
83345386Swpaul	    if (!disk->chunks)
83445386Swpaul		msgFatal("No chunk list found for %s!", disk->name);
83545386Swpaul	    for (c1 = disk->chunks->part; c1; c1 = c1->next) {
83645386Swpaul		if (c1->type == freebsd) {
83745386Swpaul		    dialog_clear_norefresh();
83845386Swpaul		    msgNotify("Making slice entries for %s", c1->name);
83945386Swpaul		    if (vsystem("cd /dev; sh MAKEDEV %sh", c1->name)) {
84045386Swpaul			msgConfirm("Unable to make slice entries for %s!", c1->name);
84145386Swpaul			return DITEM_FAILURE | DITEM_RESTORE;
84245386Swpaul		    }
84345386Swpaul		}
84445386Swpaul	    }
84545386Swpaul	}
84645386Swpaul
84745386Swpaul	/* BOGON #2: We leave /etc in a bad state */
84845386Swpaul	chmod("/etc", 0755);
84945386Swpaul
85045386Swpaul	/* BOGON #3: No /var/db/mountdtab complains */
85145386Swpaul	Mkdir("/var/db");
85245386Swpaul	creat("/var/db/mountdtab", 0644);
85345386Swpaul
85445386Swpaul	/* BOGON #4: /compat created by default in root fs */
855102336Salfred	Mkdir("/usr/compat");
856102336Salfred	vsystem("ln -s usr/compat /compat");
85745386Swpaul
85845386Swpaul	/* BOGON #5: aliases database not build for bin */
85945386Swpaul	vsystem("newaliases");
86045386Swpaul
86145386Swpaul	/* Now run all the mtree stuff to fix things up */
86245386Swpaul        vsystem("mtree -deU -f /etc/mtree/BSD.root.dist -p /");
86345386Swpaul        vsystem("mtree -deU -f /etc/mtree/BSD.var.dist -p /var");
86445386Swpaul        vsystem("mtree -deU -f /etc/mtree/BSD.usr.dist -p /usr");
86545386Swpaul
86645386Swpaul	/* Do all the last ugly work-arounds here */
86745386Swpaul    }
86845386Swpaul    return DITEM_SUCCESS | DITEM_RESTORE;
86945386Swpaul}
87045386Swpaul
87145386Swpaul/* Fix side-effects from the the XFree86 installation */
87245386Swpaulint
87345386SwpaulinstallFixupXFree(dialogMenuItem *self)
87445386Swpaul{
87545386Swpaul    /* BOGON #1:  XFree86 requires various specialized fixups */
876102336Salfred    if (directory_exists("/usr/X11R6")) {
877102336Salfred	dialog_clear_norefresh();
87845386Swpaul	msgNotify("Fixing permissions in XFree86 tree..");
87945386Swpaul	vsystem("chmod -R a+r /usr/X11R6");
88045386Swpaul	vsystem("find /usr/X11R6 -type d | xargs chmod a+x");
88145386Swpaul
88245386Swpaul	/* Also do bogus minimal package registration so ports don't whine */
88345386Swpaul	if (file_readable("/usr/X11R6/lib/X11/pkgreg.tar.gz")) {
88445386Swpaul	    dialog_clear_norefresh();
88545386Swpaul	    msgNotify("Installing package metainfo..");
88645386Swpaul	    vsystem("tar xpzf /usr/X11R6/lib/X11/pkgreg.tar.gz -C / && rm /usr/X11R6/lib/X11/pkgreg.tar.gz");
88745386Swpaul	}
88845386Swpaul    }
88945386Swpaul    return DITEM_SUCCESS | DITEM_RESTORE;
89045386Swpaul}
89145386Swpaul
89245386Swpaul/* Go newfs and/or mount all the filesystems we've been asked to */
89345386Swpaulint
89445386SwpaulinstallFilesystems(dialogMenuItem *self)
89545386Swpaul{
89645386Swpaul    int i, mountfailed;
89745386Swpaul    Disk *disk;
89845386Swpaul    Chunk *c1, *c2, *rootdev, *swapdev;
89945386Swpaul    Device **devs;
90045386Swpaul    PartInfo *root;
90145386Swpaul    char dname[80];
90245386Swpaul    extern int MakeDevChunk(Chunk *c, char *n);
90345386Swpaul    Boolean upgrade = FALSE;
904102336Salfred
905102336Salfred    /* If we've already done this, bail out */
90645386Swpaul    if (!variable_cmp(DISK_LABELLED, "written"))
90745386Swpaul	return DITEM_SUCCESS;
90845386Swpaul
90945386Swpaul    upgrade = !variable_cmp(SYSTEM_STATE, "upgrade");
91045386Swpaul    if (!checkLabels(TRUE, &rootdev, &swapdev, NULL, NULL, NULL, NULL))
91145386Swpaul	return DITEM_FAILURE;
91245386Swpaul
91345386Swpaul    if (rootdev)
91445386Swpaul	root = (PartInfo *)rootdev->private_data;
915131654Sbms    else
91645386Swpaul	root = NULL;
91745386Swpaul
91845386Swpaul    command_clear();
91945386Swpaul    if (swapdev && RunningAsInit) {
92045386Swpaul	/* As the very first thing, try to get ourselves some swap space */
92145386Swpaul	sprintf(dname, "/dev/%s", swapdev->name);
92245386Swpaul	if (!Fake && (!MakeDevChunk(swapdev, "/dev") || !file_readable(dname))) {
92345386Swpaul	    msgConfirm("Unable to make device node for %s in /dev!\n"
92445386Swpaul		       "The creation of filesystems will be aborted.", dname);
92545386Swpaul	    return DITEM_FAILURE;
92645386Swpaul	}
92745386Swpaul
92845386Swpaul	if (!Fake) {
92945386Swpaul	    if (!swapon(dname)) {
93045386Swpaul		dialog_clear_norefresh();
93145386Swpaul		msgNotify("Added %s as initial swap device", dname);
93245386Swpaul	    }
93345386Swpaul	    else {
93445386Swpaul		msgConfirm("WARNING!  Unable to swap to %s: %s\n"
93545386Swpaul			   "This may cause the installation to fail at some point\n"
93645386Swpaul			   "if you don't have a lot of memory.", dname, strerror(errno));
93745386Swpaul	    }
93845386Swpaul	}
93945386Swpaul    }
94045386Swpaul
94145386Swpaul    if (rootdev && RunningAsInit) {
94245386Swpaul	/* Next, create and/or mount the root device */
94345386Swpaul	sprintf(dname, "/dev/%s", rootdev->name);
94445386Swpaul	if (!Fake && (!MakeDevChunk(rootdev, "/dev") || !file_readable(dname))) {
94545386Swpaul	    msgConfirm("Unable to make device node for %s in /dev!\n"
94645386Swpaul		       "The creation of filesystems will be aborted.", dname);
94745386Swpaul	    return DITEM_FAILURE | DITEM_RESTORE;
94845386Swpaul	}
94945386Swpaul	if (strcmp(root->mountpoint, "/"))
95045386Swpaul	    msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", rootdev->name, root->mountpoint);
95145386Swpaul
95245386Swpaul	if (root->newfs && (!upgrade || !msgNoYes("You are upgrading - are you SURE you want to newfs the root partition?"))) {
95345386Swpaul	    int i;
95498849Sken
95598849Sken	    dialog_clear_norefresh();
95645386Swpaul	    msgNotify("Making a new root filesystem on %s", dname);
95745386Swpaul	    i = vsystem("%s %s", root->newfs_cmd, dname);
95845386Swpaul	    if (i) {
95945386Swpaul		msgConfirm("Unable to make new root filesystem on %s!\n"
96045386Swpaul			   "Command returned status %d", dname, i);
96145386Swpaul		return DITEM_FAILURE | DITEM_RESTORE;
96245386Swpaul	    }
96345386Swpaul	}
96445386Swpaul	else {
96545386Swpaul	    if (!upgrade) {
96645386Swpaul		msgConfirm("Warning:  Using existing root partition.  It will be assumed\n"
96745386Swpaul			   "that you have the appropriate device entries already in /dev.");
96845386Swpaul	    }
96945386Swpaul	    dialog_clear_norefresh();
97045386Swpaul	    msgNotify("Checking integrity of existing %s filesystem.", dname);
97145386Swpaul	    i = vsystem("fsck_ffs -y %s", dname);
97245386Swpaul	    if (i)
97345386Swpaul		msgConfirm("Warning: fsck returned status of %d for %s.\n"
97445386Swpaul			   "This partition may be unsafe to use.", i, dname);
97545386Swpaul	}
97645386Swpaul	if (root->soft) {
97745386Swpaul	    i = vsystem("tunefs -n enable %s", dname);
97845386Swpaul	    if (i)
979102336Salfred		msgConfirm("Warning:  Unable to enable softupdates for root filesystem on %s", dname);
980102336Salfred	}
98145386Swpaul
98245386Swpaul	/* Switch to block device */
98345386Swpaul	sprintf(dname, "/dev/%s", rootdev->name);
98445386Swpaul	if (Mount("/mnt", dname)) {
98545386Swpaul	    msgConfirm("Unable to mount the root file system on %s!  Giving up.", dname);
98645386Swpaul	    return DITEM_FAILURE | DITEM_RESTORE;
98745386Swpaul	}
98845386Swpaul
98950548Sbde	/* Mount devfs for other partitions to mount */
99045386Swpaul	Mkdir("/mnt/dev");
99145386Swpaul	if (!Fake)
99245386Swpaul	    mountfailed = mount("devfs", "/mnt/dev", 0, NULL);
993131654Sbms
99445386Swpaul	if (mountfailed) {
99545386Swpaul	    dialog_clear_norefresh();
99645386Swpaul	    msgNotify("Copying initial device files..");
99745386Swpaul	    /* Copy the boot floppy's dev files */
99845386Swpaul	    if ((root->newfs || upgrade) && vsystem("find -x /dev | cpio %s -pdum /mnt", cpioVerbosity())) {
99945386Swpaul		msgConfirm("Couldn't clone the /dev files!");
100045386Swpaul		return DITEM_FAILURE | DITEM_RESTORE;
100167405Sbmilekic	    }
100245386Swpaul	}
100345386Swpaul    }
100445386Swpaul
100567405Sbmilekic    /* Now buzz through the rest of the partitions and mount them too */
100667405Sbmilekic    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
1007131652Sbms    for (i = 0; devs[i]; i++) {
100845386Swpaul	if (!devs[i]->enabled)
100945386Swpaul	    continue;
101062793Sgallatin
101162793Sgallatin	disk = (Disk *)devs[i]->private;
101245386Swpaul	if (!disk->chunks) {
101345386Swpaul	    msgConfirm("No chunk list found for %s!", disk->name);
101445386Swpaul	    return DITEM_FAILURE | DITEM_RESTORE;
1015131654Sbms	}
101645386Swpaul	if (mountfailed) {
101745386Swpaul	    if (RunningAsInit && root && (root->newfs || upgrade)) {
101845386Swpaul		Mkdir("/mnt/dev");
101945386Swpaul		if (!Fake)
102045386Swpaul		    MakeDevDisk(disk, "/mnt/dev");
1021131654Sbms	    }
102245386Swpaul	    else if (!RunningAsInit && !Fake)
102345386Swpaul		MakeDevDisk(disk, "/dev");
102445386Swpaul	}
102545386Swpaul
102645386Swpaul	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
102745386Swpaul	    if (c1->type == freebsd) {
102845386Swpaul		for (c2 = c1->part; c2; c2 = c2->next) {
102945386Swpaul		    if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) {
1030131655Sbms			PartInfo *tmp = (PartInfo *)c2->private_data;
1031131652Sbms
103245386Swpaul			/* Already did root */
1033131652Sbms			if (c2 == rootdev)
103445386Swpaul			    continue;
103545386Swpaul
1036131654Sbms			if (tmp->newfs && (!upgrade || !msgNoYes("You are upgrading - are you SURE you want to newfs /dev/%s?", c2->name)))
103745386Swpaul			    command_shell_add(tmp->mountpoint, "%s %s/dev/%s", tmp->newfs_cmd, RunningAsInit ? "/mnt" : "", c2->name);
103845386Swpaul			else
103945386Swpaul			    command_shell_add(tmp->mountpoint, "fsck_ffs -y %s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name);
104045386Swpaul			if (tmp->soft)
1041131654Sbms			    command_shell_add(tmp->mountpoint, "tunefs -n enable %s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name);
104245386Swpaul			command_func_add(tmp->mountpoint, Mount, c2->name);
104345386Swpaul		    }
104445386Swpaul		    else if (c2->type == part && c2->subtype == FS_SWAP) {
104545386Swpaul			char fname[80];
104645386Swpaul			int i;
1047102336Salfred
1048102336Salfred			if (c2 == swapdev)
104999058Salfred			    continue;
105064837Sdwmalone			sprintf(fname, "%s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name);
105145386Swpaul			i = (Fake || swapon(fname));
105245386Swpaul			if (!i) {
1053131655Sbms			    dialog_clear_norefresh();
1054131655Sbms			    msgNotify("Added %s as an additional swap device", fname);
105545386Swpaul			}
105645386Swpaul			else {
105767405Sbmilekic			    msgConfirm("Unable to add %s as a swap device: %s", fname, strerror(errno));
105845386Swpaul			}
105945386Swpaul		    }
106067405Sbmilekic		}
106145386Swpaul	    }
106245386Swpaul	    else if (c1->type == fat && c1->private_data && (root->newfs || upgrade)) {
106367405Sbmilekic		char name[FILENAME_MAX];
106445386Swpaul
106545386Swpaul		sprintf(name, "%s/%s", RunningAsInit ? "/mnt" : "", ((PartInfo *)c1->private_data)->mountpoint);
106645386Swpaul		Mkdir(name);
106745386Swpaul	    }
106845386Swpaul	}
106964837Sdwmalone    }
107064837Sdwmalone
107164837Sdwmalone    command_sort();
107264837Sdwmalone    command_execute();
107364837Sdwmalone    if (!mountfailed && !Fake)
107464837Sdwmalone	unmount("/mnt/dev", MNT_FORCE);
107545386Swpaul    dialog_clear_norefresh();
107645386Swpaul    return DITEM_SUCCESS | DITEM_RESTORE;
107798849Sken}
107845386Swpaul
107945386Swpaulstatic char *
108045386SwpaulgetRelname(void)
108145386Swpaul{
1082102336Salfred    static char buf[64];
1083102336Salfred    size_t sz = (sizeof buf) - 1;
108445386Swpaul
108545386Swpaul    if (sysctlbyname("kern.osrelease", buf, &sz, NULL, 0) != -1) {
108645386Swpaul	buf[sz] = '\0';
108745386Swpaul	return buf;
108845386Swpaul    }
108945386Swpaul    else
109045386Swpaul	return "<unknown>";
109149036Swpaul}
1092111119Simp
109387846Sluigi/* Initialize various user-settable values to their defaults */
1094131654Sbmsint
109545386SwpaulinstallVarDefaults(dialogMenuItem *self)
1096111119Simp{
109745386Swpaul    char *cp;
109845386Swpaul
1099131654Sbms    /* Set default startup options */
110045386Swpaul    variable_set2(VAR_RELNAME,			getRelname(), 0);
110149036Swpaul    variable_set2(VAR_CPIO_VERBOSITY,		"high", 0);
110249036Swpaul    variable_set2(VAR_TAPE_BLOCKSIZE,		DEFAULT_TAPE_BLOCKSIZE, 0);
110349036Swpaul    variable_set2(VAR_INSTALL_ROOT,		"/", 0);
110449036Swpaul    variable_set2(VAR_INSTALL_CFG,		"install.cfg", 0);
110549036Swpaul    cp = getenv("EDITOR");
110645386Swpaul    if (!cp)
110745386Swpaul	cp = "/usr/bin/ee";
110848597Swpaul    variable_set2(VAR_EDITOR,			cp, 0);
110945386Swpaul    variable_set2(VAR_FTP_USER,			"ftp", 0);
111045386Swpaul    variable_set2(VAR_BROWSER_PACKAGE,		"links", 0);
111145386Swpaul    variable_set2(VAR_BROWSER_BINARY,		"/usr/local/bin/links", 0);
111245386Swpaul    variable_set2(VAR_FTP_STATE,		"passive", 0);
111345386Swpaul    variable_set2(VAR_NFS_SECURE,		"NO", -1);
1114147256Sbrooks    if (OnVTY)
111558698Sjlemon	    variable_set2(VAR_FIXIT_TTY,		"standard", 0);
111649036Swpaul    else
111745386Swpaul	    variable_set2(VAR_FIXIT_TTY,		"serial", 0);
111845386Swpaul    variable_set2(VAR_PKG_TMPDIR,		"/usr/tmp", 0);
1119131654Sbms    variable_set2(VAR_MEDIA_TIMEOUT,		itoa(MEDIA_TIMEOUT), 0);
112045386Swpaul    if (getpid() != 1)
112145386Swpaul	variable_set2(SYSTEM_STATE,		"update", 0);
112245386Swpaul    else
112345386Swpaul	variable_set2(SYSTEM_STATE,		"init", 0);
112445386Swpaul    variable_set2(VAR_NEWFS_ARGS,		"-b 8192 -f 1024", 0);
112545386Swpaul    variable_set2(VAR_CONSTERM,                 "NO", 0);
1126102336Salfred    return DITEM_SUCCESS;
1127102336Salfred}
112845386Swpaul
112945386Swpaul/* Load the environment up from various system configuration files */
113045386Swpaulvoid
113145386SwpaulinstallEnvironment(void)
113245386Swpaul{
113345386Swpaul    configEnvironmentRC_conf();
113445386Swpaul    if (file_readable("/etc/resolv.conf"))
113549036Swpaul	configEnvironmentResolv("/etc/resolv.conf");
1136111119Simp}
113745386Swpaul
1138131654Sbms/* Copy the boot floppy contents into /stand */
113945386SwpaulBoolean
114049036SwpaulcopySelf(void)
114149036Swpaul{
114249036Swpaul    int i;
114349036Swpaul
114449036Swpaul    if (file_readable("/boot.help"))
114545386Swpaul	vsystem("cp /boot.help /mnt");
114649036Swpaul    msgWeHaveOutput("Copying the boot floppy to /stand on root filesystem");
114748597Swpaul    i = vsystem("find -x /stand | cpio %s -pdum /mnt", cpioVerbosity());
114845386Swpaul    if (i) {
114945386Swpaul	msgConfirm("Copy returned error status of %d!", i);
115045386Swpaul	return FALSE;
115145386Swpaul    }
115245386Swpaul
1153147256Sbrooks    /* Copy the /etc files into their rightful place */
115458698Sjlemon    if (vsystem("cd /mnt/stand; find etc | cpio %s -pdum /mnt", cpioVerbosity())) {
115549036Swpaul	msgConfirm("Couldn't copy up the /etc files!");
115645386Swpaul	return TRUE;
115745386Swpaul    }
1158131654Sbms    return TRUE;
115945386Swpaul}
116045386Swpaul
116198849Skenstatic void
116298849Skencreate_termcap(void)
116345386Swpaul{
116445386Swpaul    FILE *fp;
116545386Swpaul
116645386Swpaul    const char *caps[] = {
1167102336Salfred	termcap_vt100, termcap_cons25, termcap_cons25_m, termcap_cons25r,
1168102336Salfred	termcap_cons25r_m, termcap_cons25l1, termcap_cons25l1_m,
116945386Swpaul	termcap_xterm, NULL,
117045386Swpaul    };
117145386Swpaul    const char **cp;
117245386Swpaul
117345386Swpaul    if (!file_readable(TERMCAP_FILE)) {
117445386Swpaul	Mkdir("/usr/share/misc");
117545386Swpaul	fp = fopen(TERMCAP_FILE, "w");
117649036Swpaul	if (!fp) {
117745386Swpaul	    msgConfirm("Unable to initialize termcap file. Some screen-oriented\nutilities may not work.");
117845386Swpaul	    return;
117945386Swpaul	}
1180111119Simp	cp = caps;
118145386Swpaul	while (*cp)
1182131654Sbms	    fprintf(fp, "%s\n", *(cp++));
118345386Swpaul	fclose(fp);
118445386Swpaul    }
118545386Swpaul}
118645386Swpaul