install.c revision 34466
1193323Sed/*
2193323Sed * The new sysinstall program.
3193323Sed *
4193323Sed * This is probably the last program in the `sysinstall' line - the next
5193323Sed * generation being essentially a complete rewrite.
6193323Sed *
7193323Sed * $Id: install.c,v 1.206 1998/03/09 15:00:56 jkh Exp $
8193323Sed *
9193323Sed * Copyright (c) 1995
10193323Sed *	Jordan Hubbard.  All rights reserved.
11193323Sed *
12193323Sed * Redistribution and use in source and binary forms, with or without
13193323Sed * modification, are permitted provided that the following conditions
14193323Sed * are met:
15193323Sed * 1. Redistributions of source code must retain the above copyright
16193323Sed *    notice, this list of conditions and the following disclaimer,
17193323Sed *    verbatim and that no modifications are made prior to this
18218893Sdim *    point in the file.
19198090Srdivacky * 2. Redistributions in binary form must reproduce the above copyright
20193323Sed *    notice, this list of conditions and the following disclaimer in the
21193323Sed *    documentation and/or other materials provided with the distribution.
22193323Sed *
23193323Sed * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
24234353Sdim * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25234353Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26234353Sdim * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
27234353Sdim * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28234353Sdim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29234353Sdim * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
30234353Sdim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32234353Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33234353Sdim * SUCH DAMAGE.
34234353Sdim *
35234353Sdim */
36234353Sdim
37234353Sdim#include "sysinstall.h"
38234353Sdim#include "uc_main.h"
39234353Sdim#include <ctype.h>
40234353Sdim#include <sys/disklabel.h>
41234353Sdim#include <sys/errno.h>
42234353Sdim#include <sys/ioctl.h>
43234353Sdim#include <sys/fcntl.h>
44234353Sdim#include <sys/wait.h>
45234353Sdim#include <sys/param.h>
46234353Sdim#define MSDOSFS
47234353Sdim#include <sys/mount.h>
48234353Sdim#include <ufs/ufs/ufsmount.h>
49239462Sdim#include <msdosfs/msdosfsmount.h>
50234353Sdim#undef MSDOSFS
51234353Sdim#include <sys/stat.h>
52234353Sdim#include <unistd.h>
53234353Sdim
54234353Sdimstatic void	create_termcap(void);
55234353Sdimstatic void	fixit_common(void);
56234353Sdim#ifdef SAVE_USERCONFIG
57234353Sdimstatic void	save_userconfig_to_kernel(char *);
58234353Sdim#endif
59234353Sdim
60234353Sdim#define TERMCAP_FILE	"/usr/share/misc/termcap"
61234353Sdim
62234353Sdimstatic void	installConfigure(void);
63234353Sdim
64234353SdimBoolean
65202375SrdivackycheckLabels(Boolean whinge, Chunk **rdev, Chunk **sdev, Chunk **udev, Chunk **vdev)
66202375Srdivacky{
67193323Sed    Device **devs;
68193323Sed    Boolean status;
69193323Sed    Disk *disk;
70234353Sdim    Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev;
71195340Sed    int i;
72198090Srdivacky
73195340Sed    /* Don't allow whinging if noWarn is set */
74195340Sed    if (variable_get(VAR_NO_WARN))
75193323Sed	whinge = FALSE;
76234353Sdim
77234353Sdim    status = TRUE;
78234353Sdim    *rdev = *sdev = *udev = *vdev = rootdev = swapdev = usrdev = vardev = NULL;
79193323Sed
80193323Sed    /* We don't need to worry about root/usr/swap if we're already multiuser */
81193323Sed    if (!RunningAsInit)
82193323Sed	return status;
83234353Sdim
84234353Sdim    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
85234353Sdim    /* First verify that we have a root device */
86193323Sed    for (i = 0; devs[i]; i++) {
87193323Sed	if (!devs[i]->enabled)
88193323Sed	    continue;
89234353Sdim	disk = (Disk *)devs[i]->private;
90234353Sdim	msgDebug("Scanning disk %s for root filesystem\n", disk->name);
91234353Sdim	if (!disk->chunks)
92234353Sdim	    msgFatal("No chunk list found for %s!", disk->name);
93234353Sdim	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
94193323Sed	    if (c1->type == freebsd) {
95234353Sdim		for (c2 = c1->part; c2; c2 = c2->next) {
96234353Sdim		    if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) {
97239462Sdim			if (c2->flags & CHUNK_IS_ROOT) {
98234353Sdim			    if (rootdev) {
99234353Sdim				if (whinge)
100234353Sdim				    msgConfirm("WARNING:  You have more than one root device set?!\n"
101193323Sed					       "Using the first one found.");
102234353Sdim				continue;
103234353Sdim			    }
104234353Sdim			    else {
105234353Sdim				rootdev = c2;
106234353Sdim				if (isDebug())
107234353Sdim				    msgDebug("Found rootdev at %s!\n", rootdev->name);
108193323Sed			    }
109193323Sed			}
110234353Sdim			else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/usr")) {
111234353Sdim			    if (usrdev) {
112234353Sdim				if (whinge)
113234353Sdim				    msgConfirm("WARNING:  You have more than one /usr filesystem.\n"
114193323Sed					       "Using the first one found.");
115193323Sed				continue;
116193323Sed			    }
117234353Sdim			    else {
118234353Sdim				usrdev = c2;
119234353Sdim				if (isDebug())
120234353Sdim				    msgDebug("Found usrdev at %s!\n", usrdev->name);
121193323Sed			    }
122193323Sed			}
123193323Sed			else if (!strcmp(((PartInfo *)c2->private_data)->mountpoint, "/var")) {
124234353Sdim			    if (vardev) {
125193323Sed				if (whinge)
126193323Sed				    msgConfirm("WARNING:  You have more than one /var filesystem.\n"
127234353Sdim					       "Using the first one found.");
128218893Sdim				continue;
129218893Sdim			    }
130234353Sdim			    else {
131234353Sdim				vardev = c2;
132234353Sdim				if (isDebug())
133234353Sdim				    msgDebug("Found vardev at %s!\n", vardev->name);
134204642Srdivacky			    }
135198090Srdivacky			}
136193323Sed		    }
137193323Sed		}
138193323Sed	    }
139193323Sed	}
140193323Sed    }
141193323Sed
142193323Sed    /* Now check for swap devices */
143193323Sed    for (i = 0; devs[i]; i++) {
144193323Sed	if (!devs[i]->enabled)
145193323Sed	    continue;
146193323Sed	disk = (Disk *)devs[i]->private;
147198090Srdivacky	msgDebug("Scanning disk %s for swap partitions\n", disk->name);
148198090Srdivacky	if (!disk->chunks)
149198090Srdivacky	    msgFatal("No chunk list found for %s!", disk->name);
150198090Srdivacky	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
151198090Srdivacky	    if (c1->type == freebsd) {
152198090Srdivacky		for (c2 = c1->part; c2; c2 = c2->next) {
153204792Srdivacky		    if (c2->type == part && c2->subtype == FS_SWAP && !swapdev) {
154198090Srdivacky			swapdev = c2;
155198090Srdivacky			if (isDebug())
156198090Srdivacky			    msgDebug("Found swapdev at %s!\n", swapdev->name);
157203954Srdivacky			break;
158204792Srdivacky		    }
159226633Sdim		}
160226633Sdim	    }
161226633Sdim	}
162226633Sdim    }
163234353Sdim
164249423Sdim    /* Copy our values over */
165243830Sdim    *rdev = rootdev;
166243830Sdim    *sdev = swapdev;
167249423Sdim    *udev = usrdev;
168263508Sdim    *vdev = vardev;
169263508Sdim
170263508Sdim    if (!rootdev && whinge) {
171243830Sdim	msgConfirm("No root device found - you must label a partition as /\n"
172193323Sed		   "in the label editor.");
173193323Sed	status = FALSE;
174193323Sed    }
175203954Srdivacky    if (!swapdev && whinge) {
176198090Srdivacky	msgConfirm("No swap devices found - you must create at least one\n"
177198090Srdivacky		   "swap partition.");
178198090Srdivacky	status = FALSE;
179203954Srdivacky    }
180203954Srdivacky    if (!usrdev && whinge) {
181226633Sdim	msgConfirm("WARNING:  No /usr filesystem found.  This is not technically\n"
182203954Srdivacky		   "an error if your root filesystem is big enough (or you later\n"
183203954Srdivacky		   "intend to mount your /usr filesystem over NFS), but it may otherwise\n"
184203954Srdivacky		   "cause you trouble if you're not exactly sure what you are doing!");
185203954Srdivacky    }
186203954Srdivacky    if (!vardev && whinge && variable_cmp(SYSTEM_STATE, "upgrade")) {
187203954Srdivacky	msgConfirm("WARNING:  No /var filesystem found.  This is not technically\n"
188203954Srdivacky		   "an error if your root filesystem is big enough (or you later\n"
189203954Srdivacky		   "intend to link /var to someplace else), but it may otherwise\n"
190203954Srdivacky		   "cause your root filesystem to fill up if you receive lots of mail\n"
191203954Srdivacky		   "or edit large temporary files.");
192203954Srdivacky    }
193203954Srdivacky    return status;
194203954Srdivacky}
195203954Srdivacky
196203954Srdivackystatic int
197203954SrdivackyinstallInitial(void)
198203954Srdivacky{
199203954Srdivacky    static Boolean alreadyDone = FALSE;
200203954Srdivacky
201203954Srdivacky    if (alreadyDone)
202203954Srdivacky	return DITEM_SUCCESS;
203203954Srdivacky
204203954Srdivacky    if (!variable_get(DISK_LABELLED)) {
205203954Srdivacky	msgConfirm("You need to assign disk labels before you can proceed with\n"
206203954Srdivacky		   "the installation.");
207203954Srdivacky	return DITEM_FAILURE;
208203954Srdivacky    }
209203954Srdivacky    /* If it's labelled, assume it's also partitioned */
210203954Srdivacky    if (!variable_get(DISK_PARTITIONED))
211203954Srdivacky	variable_set2(DISK_PARTITIONED, "yes");
212203954Srdivacky
213203954Srdivacky    /* If we refuse to proceed, bail. */
214203954Srdivacky    dialog_clear_norefresh();
215203954Srdivacky    if (msgYesNo("Last Chance!  Are you SURE you want continue the installation?\n\n"
216203954Srdivacky		 "If you're running this on a disk with data you wish to save\n"
217203954Srdivacky		 "then WE STRONGLY ENCOURAGE YOU TO MAKE PROPER BACKUPS before\n"
218203954Srdivacky		 "proceeding!\n\n"
219203954Srdivacky		 "We can take no responsibility for lost disk contents!") != 0)
220203954Srdivacky	return DITEM_FAILURE | DITEM_RESTORE;
221203954Srdivacky
222203954Srdivacky    if (DITEM_STATUS(diskLabelCommit(NULL)) != DITEM_SUCCESS) {
223203954Srdivacky	msgConfirm("Couldn't make filesystems properly.  Aborting.");
224203954Srdivacky	return DITEM_FAILURE;
225263508Sdim    }
226203954Srdivacky
227203954Srdivacky    if (!copySelf()) {
228203954Srdivacky	msgConfirm("installInitial: Couldn't clone the boot floppy onto the\n"
229203954Srdivacky		   "root file system.  Aborting!");
230203954Srdivacky	return DITEM_FAILURE;
231203954Srdivacky    }
232203954Srdivacky
233226633Sdim    if (chroot("/mnt") == -1) {
234226633Sdim	msgConfirm("installInitial: Unable to chroot to %s - this is bad!",
235203954Srdivacky		   "/mnt");
236203954Srdivacky	return DITEM_FAILURE;
237203954Srdivacky    }
238203954Srdivacky
239203954Srdivacky    chdir("/");
240226633Sdim    variable_set2(RUNNING_ON_ROOT, "yes");
241226633Sdim    configResolv();
242226633Sdim
243226633Sdim    /* stick a helpful shell over on the 4th VTY */
244226633Sdim    systemCreateHoloshell();
245226633Sdim
246226633Sdim    alreadyDone = TRUE;
247226633Sdim    return DITEM_SUCCESS;
248226633Sdim}
249234353Sdim
250226633Sdimint
251198090SrdivackyinstallFixitHoloShell(dialogMenuItem *self)
252198090Srdivacky{
253198090Srdivacky    systemCreateHoloshell();
254193323Sed    return DITEM_SUCCESS;
255234353Sdim}
256193323Sed
257193323Sedint
258193323SedinstallFixitCDROM(dialogMenuItem *self)
259193323Sed{
260193323Sed    struct stat sb;
261193323Sed
262193323Sed    if (!RunningAsInit)
263193323Sed	return DITEM_SUCCESS;
264193323Sed
265193323Sed    variable_set2(SYSTEM_STATE, "fixit");
266193323Sed    (void)unlink("/mnt2");
267198090Srdivacky    (void)rmdir("/mnt2");
268218893Sdim
269218893Sdim    while (1) {
270193323Sed	msgConfirm("Please insert the second FreeBSD CDROM and press return");
271193323Sed	if (DITEM_STATUS(mediaSetCDROM(NULL)) != DITEM_SUCCESS || !mediaDevice || !mediaDevice->init(mediaDevice)) {
272193323Sed	    /* If we can't initialize it, it's probably not a FreeBSD CDROM so punt on it */
273193323Sed	    if (mediaDevice) {
274193323Sed		mediaDevice->shutdown(mediaDevice);
275193323Sed		mediaDevice = NULL;
276193323Sed	    }
277193323Sed	    if (msgYesNo("Unable to mount the CDROM - do you want to try again?") != 0)
278263508Sdim		return DITEM_FAILURE;
279193323Sed	}
280193323Sed	else
281193323Sed	    break;
282193323Sed    }
283193323Sed
284193323Sed    /* Since the fixit code expects everything to be in /mnt2, and the CDROM mounting stuff /dist, do
285193323Sed     * a little kludge dance here..
286193323Sed     */
287193323Sed    if (symlink("/dist", "/mnt2")) {
288193323Sed	msgConfirm("Unable to symlink /mnt2 to the CDROM mount point.  Please report this\n"
289203954Srdivacky		   "unexpected failure to freebsd-bugs@FreeBSD.org.");
290198090Srdivacky	return DITEM_FAILURE;
291210299Sed    }
292243830Sdim
293193323Sed    /*
294193323Sed     * If /tmp points to /mnt2/tmp from a previous fixit floppy session, it's
295193323Sed     * not very good for us if we point it to the CDROM now.  Rather make it
296193323Sed     * a directory in the root MFS then.  Experienced admins will still be
297193323Sed     * able to mount their disk's /tmp over this if they need.
298193323Sed     */
299193323Sed    if (lstat("/tmp", &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFLNK)
300193323Sed	(void)unlink("/tmp");
301193323Sed    Mkdir("/tmp");
302193323Sed
303193323Sed    /*
304193323Sed     * Since setuid binaries ignore LD_LIBRARY_PATH, we indeed need the
305263508Sdim     * ld.so.hints file.  Fortunately, it's fairly small (~ 3 KB).
306263508Sdim     */
307193323Sed    if (!file_readable("/var/run/ld.so.hints")) {
308193323Sed	Mkdir("/var/run");
309193323Sed	if (vsystem("/mnt2/sbin/ldconfig -s /mnt2/usr/lib")) {
310193323Sed	    msgConfirm("Warning: ldconfig could not create the ld.so hints file.\n"
311193323Sed		       "Dynamic executables from the CDROM likely won't work.");
312193323Sed	}
313193323Sed    }
314193323Sed
315193323Sed    /* Yet another iggly hardcoded pathname. */
316193323Sed    if (!file_readable("/usr/libexec/ld.so")) {
317193323Sed	Mkdir("/usr/libexec");
318193323Sed	if (symlink("/mnt2/usr/libexec/ld.so", "/usr/libexec/ld.so")) {
319193323Sed	    msgConfirm("Warning: could not create the symlink for ld.so.\n"
320193323Sed		       "Dynamic executables from the CDROM likely won't work.");
321193323Sed	}
322193323Sed    }
323193323Sed
324193323Sed    fixit_common();
325193323Sed
326193323Sed    mediaDevice->shutdown(mediaDevice);
327193323Sed    msgConfirm("Please remove the FreeBSD CDROM now.");
328193323Sed    return DITEM_SUCCESS;
329193323Sed}
330193323Sed
331193323Sedint
332193323SedinstallFixitFloppy(dialogMenuItem *self)
333193323Sed{
334193323Sed    struct ufs_args args;
335193323Sed
336193323Sed    if (!RunningAsInit)
337193323Sed	return DITEM_SUCCESS;
338193323Sed
339193323Sed    variable_set2(SYSTEM_STATE, "fixit");
340193323Sed    memset(&args, 0, sizeof(args));
341193323Sed    args.fspec = "/dev/fd0";
342193323Sed    Mkdir("/mnt2");
343226633Sdim
344226633Sdim    while (1) {
345226633Sdim	msgConfirm("Please insert a writable fixit floppy and press return");
346226633Sdim	if (mount("ufs", "/mnt2", 0, (caddr_t)&args) != -1)
347226633Sdim	    break;
348251662Sdim	msgConfirm("An attempt to mount the fixit floppy failed, maybe the filesystem\n"
349251662Sdim		   "is unclean.  Trying a forcible mount as a last resort...");
350251662Sdim	if (mount("ufs", "/mnt2", MNT_FORCE, (caddr_t)&args) != -1)
351251662Sdim	    break;
352251662Sdim	if (msgYesNo("Unable to mount the fixit floppy - do you want to try again?") != 0)
353251662Sdim	    return DITEM_FAILURE;
354251662Sdim    }
355251662Sdim
356251662Sdim    if (!directory_exists("/tmp"))
357251662Sdim	(void)symlink("/mnt2/tmp", "/tmp");
358251662Sdim
359251662Sdim    fixit_common();
360263508Sdim
361263508Sdim    unmount("/mnt2", MNT_FORCE);
362251662Sdim    msgConfirm("Please remove the fixit floppy now.");
363263508Sdim    return DITEM_SUCCESS;
364263508Sdim}
365251662Sdim
366263508Sdim/*
367263508Sdim * The common code for both fixit variants.
368251662Sdim */
369263508Sdimstatic void
370263508Sdimfixit_common(void)
371251662Sdim{
372251662Sdim    pid_t child;
373263508Sdim    int waitstatus;
374263508Sdim
375263508Sdim    if (!directory_exists("/var/tmp/vi.recover")) {
376263508Sdim	if (DITEM_STATUS(Mkdir("/var/tmp/vi.recover")) != DITEM_SUCCESS) {
377263508Sdim	    msgConfirm("Warning:  Was unable to create a /var/tmp/vi.recover directory.\n"
378263508Sdim		       "vi will kvetch and moan about it as a result but should still\n"
379263508Sdim		       "be essentially usable.");
380251662Sdim	}
381251662Sdim    }
382251662Sdim    if (!directory_exists("/bin"))
383251662Sdim	(void)Mkdir("/bin");
384251662Sdim    (void)symlink("/stand/sh", "/bin/sh");
385251662Sdim    /* Link the /etc/ files */
386251662Sdim    if (DITEM_STATUS(Mkdir("/etc")) != DITEM_SUCCESS)
387251662Sdim	msgConfirm("Unable to create an /etc directory!  Things are weird on this floppy..");
388251662Sdim    else if ((symlink("/mnt2/etc/spwd.db", "/etc/spwd.db") == -1 && errno != EEXIST) ||
389251662Sdim	     (symlink("/mnt2/etc/protocols", "/etc/protocols") == -1 && errno != EEXIST) ||
390251662Sdim	     (symlink("/mnt2/etc/services", "/etc/services") == -1 && errno != EEXIST))
391251662Sdim	msgConfirm("Couldn't symlink the /etc/ files!  I'm not sure I like this..");
392263508Sdim    if (!file_readable(TERMCAP_FILE))
393251662Sdim	create_termcap();
394251662Sdim    if (!(child = fork())) {
395263508Sdim	int i, fd;
396251662Sdim	struct termios foo;
397251662Sdim	extern int login_tty(int);
398263508Sdim
399251662Sdim	ioctl(0, TIOCNOTTY, NULL);
400251662Sdim	for (i = getdtablesize(); i >= 0; --i)
401263508Sdim	    close(i);
402251662Sdim	fd = open("/dev/ttyv3", O_RDWR);
403251662Sdim	ioctl(0, TIOCSCTTY, &fd);
404251662Sdim	dup2(0, 1);
405234353Sdim	dup2(0, 2);
406234353Sdim	DebugFD = 2;
407234353Sdim	if (login_tty(fd) == -1)
408234353Sdim	    msgDebug("fixit: I can't set the controlling terminal.\n");
409223017Sdim
410193323Sed	signal(SIGTTOU, SIG_IGN);
411249423Sdim	if (tcgetattr(0, &foo) != -1) {
412249423Sdim	    foo.c_cc[VERASE] = '\010';
413249423Sdim	    if (tcsetattr(0, TCSANOW, &foo) == -1)
414263508Sdim		msgDebug("fixit shell: Unable to set erase character.\n");
415223017Sdim	}
416249423Sdim	else
417193323Sed	    msgDebug("fixit shell: Unable to get terminal attributes!\n");
418193323Sed	setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/stand:"
419263508Sdim	       "/mnt2/stand:/mnt2/bin:/mnt2/sbin:/mnt2/usr/bin:/mnt2/usr/sbin", 1);
420193323Sed	/* use the .profile from the fixit medium */
421193323Sed	setenv("HOME", "/mnt2", 1);
422263508Sdim	chdir("/mnt2");
423193323Sed	execlp("sh", "-sh", 0);
424234353Sdim	msgDebug("fixit shell: Failed to execute shell!\n");
425263508Sdim	_exit(1);;
426263508Sdim    }
427263508Sdim    else {
428263508Sdim	msgNotify("Waiting for fixit shell to exit.  Go to VTY4 now by\n"
429263508Sdim		  "typing ALT-F4.  When you are done, type ``exit'' to exit\n"
430263508Sdim		  "the fixit shell and be returned here.");
431263508Sdim	(void)waitpid(child, &waitstatus, 0);
432263508Sdim    }
433263508Sdim    dialog_clear();
434263508Sdim}
435263508Sdim
436263508Sdim
437263508Sdimint
438263508SdiminstallExpress(dialogMenuItem *self)
439263508Sdim{
440263508Sdim    int i;
441263508Sdim
442263508Sdim    variable_set2(SYSTEM_STATE, "express");
443263508Sdim    if (DITEM_STATUS((i = diskPartitionEditor(self))) == DITEM_FAILURE)
444263508Sdim	return i;
445263508Sdim
446263508Sdim    if (DITEM_STATUS((i = diskLabelEditor(self))) == DITEM_FAILURE)
447234353Sdim	return i;
448234353Sdim
449234353Sdim    dialog_clear_norefresh();
450234353Sdim    if (DITEM_STATUS((i = installCommit(self))) == DITEM_SUCCESS) {
451234353Sdim	i |= DITEM_LEAVE_MENU;
452234353Sdim	/* Give user the option of one last configuration spree */
453234353Sdim	installConfigure();
454234353Sdim    }
455234353Sdim    return i | DITEM_RESTORE;
456234353Sdim}
457193323Sed
458234353Sdim/* Novice mode installation */
459234353Sdimint
460234353SdiminstallNovice(dialogMenuItem *self)
461234353Sdim{
462234353Sdim    int i, tries = 0;
463234353Sdim    Device **devs;
464198090Srdivacky
465234353Sdim    variable_set2(SYSTEM_STATE, "novice");
466234353Sdim    dialog_clear_norefresh();
467234353Sdim    msgConfirm("In the next menu, you will need to set up a DOS-style (\"fdisk\") partitioning\n"
468234353Sdim	       "scheme for your hard disk.  If you simply wish to devote all disk space\n"
469198090Srdivacky	       "to FreeBSD (overwriting anything else that might be on the disk(s) selected)\n"
470234353Sdim	       "then use the (A)ll command to select the default partitioning scheme followed\n"
471234353Sdim	       "by a (Q)uit.  If you wish to allocate only free space to FreeBSD, move to a\n"
472234353Sdim	       "partition marked \"unused\" and use the (C)reate command.");
473234353Sdim
474234353Sdimnodisks:
475234353Sdim    if (DITEM_STATUS(diskPartitionEditor(self)) == DITEM_FAILURE)
476234353Sdim	return DITEM_FAILURE;
477195340Sed
478195340Sed    if (diskGetSelectCount(&devs) <= 0 && tries < 3) {
479204642Srdivacky	msgConfirm("You need to select some disks to operate on!  Be sure to use SPACE\n"
480204642Srdivacky		   "instead of RETURN in the disk selection menu when selecting a disk.");
481204642Srdivacky	++tries;
482204642Srdivacky	goto nodisks;
483234353Sdim    }
484234353Sdim
485234353Sdim    dialog_clear_norefresh();
486204642Srdivacky    msgConfirm("Next, you need to create BSD partitions inside of the fdisk partition(s)\n"
487234353Sdim	       "just created.  If you have a reasonable amount of disk space (200MB or more)\n"
488234353Sdim	       "and don't have any special requirements, simply use the (A)uto command to\n"
489234353Sdim	       "allocate space automatically.  If you have more specific needs or just don't\n"
490263508Sdim	       "care for the layout chosen by (A)uto, press F1 for more information on\n"
491234353Sdim	       "manual layout.");
492234353Sdim
493234353Sdim    if (DITEM_STATUS(diskLabelEditor(self)) == DITEM_FAILURE)
494234353Sdim	return DITEM_FAILURE;
495234353Sdim
496234353Sdim    dialog_clear_norefresh();
497234353Sdim    if (DITEM_STATUS((i = installCommit(self))) == DITEM_FAILURE) {
498234353Sdim	dialog_clear_norefresh();
499234353Sdim	msgConfirm("Installation completed with some errors.  You may wish to\n"
500234353Sdim		   "scroll through the debugging messages on VTY1 with the\n"
501234353Sdim		   "scroll-lock feature.  You can also chose \"No\" at the next\n"
502234353Sdim		   "prompt and go back into the installation menus to try and retry\n"
503234353Sdim		   "whichever operations have failed.");
504234353Sdim	return i | DITEM_RESTORE;
505234353Sdim
506193323Sed    }
507234353Sdim    else {
508234353Sdim	dialog_clear_norefresh();
509234353Sdim	msgConfirm("Congratulations!  You now have FreeBSD installed on your system.\n\n"
510234353Sdim		   "We will now move on to the final configuration questions.\n"
511234353Sdim		   "For any option you do not wish to configure, simply select\n"
512234353Sdim		   "No.\n\n"
513234353Sdim		   "If you wish to re-enter this utility after the system is up, you\n"
514195340Sed		   "may do so by typing: /stand/sysinstall.");
515195340Sed    }
516193323Sed    if (mediaDevice->type != DEVICE_TYPE_FTP && mediaDevice->type != DEVICE_TYPE_NFS) {
517234353Sdim	if (!msgYesNo("Would you like to configure any Ethernet or SLIP/PPP network devices?")) {
518234353Sdim	    Device *tmp;
519234353Sdim
520234353Sdim	    dialog_clear_norefresh();
521234353Sdim	    tmp = tcpDeviceSelect();
522234353Sdim	    dialog_clear_norefresh();
523193323Sed	    if (tmp && !msgYesNo("Would you like to bring the %s interface up right now?", tmp->name))
524193323Sed		if (!tmp->init(tmp))
525234353Sdim		    msgConfirm("Initialization of %s device failed.", tmp->name);
526234353Sdim	}
527234353Sdim    }
528234353Sdim
529234353Sdim    dialog_clear_norefresh();
530193323Sed    if (!msgYesNo("Will this machine be an IP gateway (e.g. will it forward packets\n"
531234353Sdim		  "between interfaces)?"))
532234353Sdim	variable_set2("gateway_enable", "YES");
533234353Sdim
534234353Sdim    dialog_clear_norefresh();
535234353Sdim    if (!msgYesNo("Do you want to allow anonymous FTP connections to this machine?"))
536234353Sdim	configAnonFTP(self);
537193323Sed
538193323Sed    dialog_clear_norefresh();
539234353Sdim    if (!msgYesNo("Do you want to configure this machine as an NFS server?"))
540234353Sdim	configNFSServer(self);
541234353Sdim
542234353Sdim    dialog_clear_norefresh();
543234353Sdim    if (!msgYesNo("Do you want to configure this machine as an NFS client?"))
544193323Sed	variable_set2("nfs_client", "YES");
545234353Sdim
546234353Sdim    dialog_clear_norefresh();
547234353Sdim    if (!msgYesNo("Would you like to customize your system console settings?")) {
548234353Sdim	WINDOW *w = savescr();
549234353Sdim
550234353Sdim	dmenuOpenSimple(&MenuSyscons, FALSE);
551193323Sed	restorescr(w);
552193323Sed    }
553234353Sdim
554234353Sdim    dialog_clear_norefresh();
555234353Sdim    if (!msgYesNo("Would you like to set this machine's time zone now?")) {
556234353Sdim	WINDOW *w = savescr();
557234353Sdim
558193323Sed	dialog_clear();
559193323Sed	systemExecute("tzsetup");
560234353Sdim	restorescr(w);
561239462Sdim    }
562239462Sdim
563239462Sdim    dialog_clear_norefresh();
564239462Sdim    if (!msgYesNo("Does this system have a mouse attached to it?")) {
565239462Sdim	WINDOW *w = savescr();
566239462Sdim
567239462Sdim	dmenuOpenSimple(&MenuMouse, FALSE);
568239462Sdim	restorescr(w);
569239462Sdim    }
570263508Sdim
571263508Sdim    /* Now would be a good time to checkpoint the configuration data */
572263508Sdim    configRC_conf("/etc/rc.conf");
573263508Sdim    sync();
574263508Sdim
575263508Sdim    if (directory_exists("/usr/X11R6")) {
576263508Sdim	dialog_clear_norefresh();
577263508Sdim	if (!msgYesNo("Would you like to configure your X server at this time?"))
578234353Sdim	    configXEnvironment(self);
579234353Sdim    }
580234353Sdim
581234353Sdim    dialog_clear_norefresh();
582207618Srdivacky    if (!msgYesNo("The FreeBSD package collection is a collection of hundreds of ready-to-run\n"
583193323Sed		  "applications, from text editors to games to WEB servers and more.  Would you\n"
584234353Sdim		  "like to browse the collection now?"))
585234353Sdim	configPackages(self);
586234353Sdim
587234353Sdim    dialog_clear_norefresh();
588234353Sdim    if (!msgYesNo("Would you like to add any initial user accounts to the system?\n"
589218893Sdim		  "Adding at least one account for yourself at this stage is suggested\n"
590218893Sdim		  "since working as the \"root\" user is dangerous (it is easy to do\n"
591234353Sdim		  "things which adversely affect the entire system)."))
592234353Sdim	configUsers(self);
593234353Sdim
594234353Sdim    dialog_clear_norefresh();
595193323Sed    msgConfirm("Now you must set the system manager's password.\n"
596234353Sdim	       "This is the password you'll use to log in as \"root\".");
597234353Sdim    {
598234353Sdim	WINDOW *w = savescr();
599234353Sdim
600234353Sdim	if (!systemExecute("passwd root"))
601234353Sdim	    variable_set2("root_password", "YES");
602234353Sdim	restorescr(w);
603234353Sdim    }
604234353Sdim
605234353Sdim    dialog_clear_norefresh();
606234353Sdim    if (!msgYesNo("Would you like to register your FreeBSD system at this time?\n\n"
607234353Sdim		  "PLEASE, take just 5 minutes to do this.  If we're ever to get any\n"
608234353Sdim		  "significant base of commercial software for FreeBSD, we need to\n"
609234353Sdim		  "be able to provide more information about the size of our user community.\n"
610234353Sdim		  "This is where your registration can really help us, and you can also\n"
611234353Sdim		  "sign up for the new FreeBSD newsletter (its free!) at the same time.\n"))
612234353Sdim	configRegister(NULL);
613234353Sdim    else {
614234353Sdim	dialog_clear_norefresh();
615234353Sdim	msgConfirm("OK, but if you should change your mind then you always can register\n"
616234353Sdim		   "later by typing ``/stand/sysinstall register'' or by simply visiting our\n"
617234353Sdim		   "web site at http://www.freebsd.org/register.html");
618234353Sdim
619234353Sdim    }
620234353Sdim    /* XXX Put whatever other nice configuration questions you'd like to ask the user here XXX */
621234353Sdim
622234353Sdim    /* Give user the option of one last configuration spree */
623234353Sdim    dialog_clear_norefresh();
624234353Sdim    installConfigure();
625234353Sdim
626234353Sdim    return DITEM_LEAVE_MENU | DITEM_RESTORE;
627234353Sdim}
628234353Sdim
629234353Sdim/* The version of commit we call from the Install Custom menu */
630234353Sdimint
631234353SdiminstallCustomCommit(dialogMenuItem *self)
632234353Sdim{
633234353Sdim    int i;
634234353Sdim
635234353Sdim    dialog_clear_norefresh();
636234353Sdim    i = installCommit(self);
637234353Sdim    if (DITEM_STATUS(i) == DITEM_SUCCESS) {
638234353Sdim	/* Give user the option of one last configuration spree */
639234353Sdim	installConfigure();
640234353Sdim	return i;
641234353Sdim    }
642234353Sdim    else
643234353Sdim	msgConfirm("The commit operation completed with errors.  Not\n"
644234353Sdim		   "updating /etc files.");
645234353Sdim    return i;
646234353Sdim}
647234353Sdim
648234353Sdim/*
649234353Sdim * What happens when we finally decide to going ahead with the installation.
650234353Sdim *
651234353Sdim * This is broken into multiple stages so that the user can do a full
652234353Sdim * installation but come back here again to load more distributions,
653234353Sdim * perhaps from a different media type.  This would allow, for
654234353Sdim * example, the user to load the majority of the system from CDROM and
655234353Sdim * then use ftp to load just the DES dist.
656234353Sdim */
657234353Sdimint
658234353SdiminstallCommit(dialogMenuItem *self)
659234353Sdim{
660234353Sdim    int i;
661234353Sdim    char *str;
662234353Sdim    Boolean need_bin;
663234353Sdim
664234353Sdim    if (!Dists)
665234353Sdim	distConfig(NULL);
666234353Sdim
667234353Sdim    if (!Dists)
668234353Sdim	if (!dmenuOpenSimple(&MenuDistributions, FALSE) && !Dists)
669234353Sdim	    return DITEM_FAILURE | DITEM_RESTORE;
670234353Sdim
671234353Sdim    if (!mediaVerify())
672234353Sdim	return DITEM_FAILURE | DITEM_RESTORE;
673234353Sdim
674234353Sdim    str = variable_get(SYSTEM_STATE);
675234353Sdim    if (isDebug())
676234353Sdim	msgDebug("installCommit: System state is `%s'\n", str);
677234353Sdim
678234353Sdim    if (RunningAsInit) {
679234353Sdim	/* Do things we wouldn't do to a multi-user system */
680234353Sdim	if (DITEM_STATUS((i = installInitial())) == DITEM_FAILURE)
681234353Sdim	    return i;
682234353Sdim	if (DITEM_STATUS((i = configFstab())) == DITEM_FAILURE)
683234353Sdim	    return i;
684234353Sdim    }
685234353Sdim
686234353Sdimtry_media:
687234353Sdim    if (!mediaDevice->init(mediaDevice)) {
688234353Sdim	if (!msgYesNo("Unable to initialize selected media. Would you like to\n"
689234353Sdim		      "adjust your media configuration and try again?")) {
690193323Sed	    mediaDevice = NULL;
691193323Sed	    if (!mediaVerify())
692193323Sed		return DITEM_FAILURE | DITEM_RESTORE;
693193323Sed	    else
694193323Sed		goto try_media;
695193323Sed	}
696193323Sed	else
697193323Sed	    return DITEM_FAILURE | DITEM_RESTORE;
698193323Sed    }
699193323Sed
700193323Sed    need_bin = Dists & DIST_BIN;
701234353Sdim    i = distExtractAll(self);
702234353Sdim    if (DITEM_STATUS(i) == DITEM_SUCCESS) {
703193323Sed	if (need_bin && !(Dists & DIST_BIN))
704193323Sed	    i = installFixup(self);
705234353Sdim    }
706234353Sdim    /* When running as init, *now* it's safe to grab the rc.foo vars */
707234353Sdim    installEnvironment();
708234353Sdim
709234353Sdim    variable_set2(SYSTEM_STATE, DITEM_STATUS(i) == DITEM_FAILURE ? "error-install" : "full-install");
710193323Sed
711234353Sdim    return i | DITEM_RESTORE;
712234353Sdim}
713234353Sdim
714234353Sdimstatic void
715234353SdiminstallConfigure(void)
716234353Sdim{
717234353Sdim    /* Final menu of last resort */
718234353Sdim    dialog_clear_norefresh();
719226633Sdim    if (!msgYesNo("Visit the general configuration menu for a chance to set\n"
720193323Sed		  "any last options?")) {
721234353Sdim	WINDOW *w = savescr();
722234353Sdim
723234353Sdim	dmenuOpenSimple(&MenuConfigure, FALSE);
724234353Sdim	restorescr(w);
725234353Sdim    }
726198090Srdivacky    configRC_conf("/etc/rc.conf");
727198090Srdivacky    sync();
728234353Sdim}
729263508Sdim
730263508Sdimint
731263508SdiminstallFixup(dialogMenuItem *self)
732263508Sdim{
733263508Sdim    Device **devs;
734263508Sdim    int i;
735263508Sdim
736263508Sdim    if (!file_readable("/kernel")) {
737263508Sdim	if (file_readable("/kernel.GENERIC")) {
738263508Sdim#ifdef SAVE_USERCONFIG
739263508Sdim	    /* Snapshot any boot -c changes back to the GENERIC kernel */
740263508Sdim	    if (!variable_cmp(VAR_RELNAME, RELEASE_NAME))
741263508Sdim		save_userconfig_to_kernel("/kernel.GENERIC");
742263508Sdim#endif
743263508Sdim	    if (vsystem("cp -p /kernel.GENERIC /kernel")) {
744234353Sdim		msgConfirm("Unable to link /kernel into place!");
745234353Sdim		return DITEM_FAILURE;
746234353Sdim	    }
747234353Sdim	}
748234353Sdim	else {
749234353Sdim	    msgConfirm("Can't find a kernel image to link to on the root file system!\n"
750234353Sdim		       "You're going to have a hard time getting this system to\n"
751234353Sdim		       "boot from the hard disk, I'm afraid!");
752234353Sdim	    return DITEM_FAILURE;
753234353Sdim	}
754198090Srdivacky    }
755198090Srdivacky
756198090Srdivacky    /* Resurrect /dev after bin distribution screws it up */
757198090Srdivacky    if (RunningAsInit) {
758198090Srdivacky	msgNotify("Remaking all devices.. Please wait!");
759198090Srdivacky	if (vsystem("cd /dev; sh MAKEDEV all")) {
760198090Srdivacky	    msgConfirm("MAKEDEV returned non-zero status");
761234353Sdim	    return DITEM_FAILURE;
762234353Sdim	}
763234353Sdim
764234353Sdim	msgNotify("Resurrecting /dev entries for slices..");
765193323Sed	devs = deviceFind(NULL, DEVICE_TYPE_DISK);
766193323Sed	if (!devs)
767193323Sed	    msgFatal("Couldn't get a disk device list!");
768193323Sed
769193323Sed	/* Resurrect the slices that the former clobbered */
770193323Sed	for (i = 0; devs[i]; i++) {
771193323Sed	    Disk *disk = (Disk *)devs[i]->private;
772193323Sed	    Chunk *c1;
773234353Sdim
774234353Sdim	    if (!devs[i]->enabled)
775234353Sdim		continue;
776234353Sdim	    if (!disk->chunks)
777234353Sdim		msgFatal("No chunk list found for %s!", disk->name);
778234353Sdim	    for (c1 = disk->chunks->part; c1; c1 = c1->next) {
779234353Sdim		if (c1->type == freebsd) {
780234353Sdim		    msgNotify("Making slice entries for %s", c1->name);
781234353Sdim		    if (vsystem("cd /dev; sh MAKEDEV %sh", c1->name)) {
782234353Sdim			msgConfirm("Unable to make slice entries for %s!", c1->name);
783234353Sdim			return DITEM_FAILURE;
784234353Sdim		    }
785234353Sdim		}
786234353Sdim	    }
787234353Sdim	}
788234353Sdim	/* XXX Do all the last ugly work-arounds here which we'll try and excise someday right?? XXX */
789234353Sdim
790234353Sdim	msgNotify("Fixing permissions..");
791198090Srdivacky	/* BOGON #1:  XFree86 extracting /usr/X11R6 with root-only perms */
792234353Sdim	if (directory_exists("/usr/X11R6")) {
793234353Sdim	    vsystem("chmod -R a+r /usr/X11R6");
794234353Sdim	    vsystem("find /usr/X11R6 -type d | xargs chmod a+x");
795234353Sdim	}
796198090Srdivacky	/* BOGON #2: We leave /etc in a bad state */
797234353Sdim	chmod("/etc", 0755);
798234353Sdim
799234353Sdim	/* BOGON #3: No /var/db/mountdtab complains */
800234353Sdim	Mkdir("/var/db");
801198090Srdivacky	creat("/var/db/mountdtab", 0644);
802234353Sdim
803234353Sdim	/* BOGON #4: /compat created by default in root fs */
804234353Sdim	Mkdir("/usr/compat");
805234353Sdim	vsystem("ln -s /usr/compat /compat");
806234353Sdim
807198090Srdivacky	/* BOGON #5: aliases database not build for bin */
808234353Sdim	vsystem("newaliases");
809234353Sdim
810234353Sdim	/* BOGON #6: deal with new boot files */
811234353Sdim	vsystem("touch /kernel.config");
812198090Srdivacky	vsystem("touch /boot.config");
813198090Srdivacky	if (file_readable("/stand/boot.help") && !file_readable("/boot.help"))
814234353Sdim	    vsystem("mv /stand/boot.help /");
815234353Sdim
816234353Sdim	/* Now run all the mtree stuff to fix things up */
817234353Sdim        vsystem("mtree -deU -f /etc/mtree/BSD.root.dist -p /");
818234353Sdim        vsystem("mtree -deU -f /etc/mtree/BSD.var.dist -p /var");
819234353Sdim        vsystem("mtree -deU -f /etc/mtree/BSD.usr.dist -p /usr");
820193323Sed    }
821193323Sed    return DITEM_SUCCESS;
822193323Sed}
823193323Sed
824193323Sed/* Go newfs and/or mount all the filesystems we've been asked to */
825193323Sedint
826234353SdiminstallFilesystems(dialogMenuItem *self)
827234353Sdim{
828234353Sdim    int i;
829234353Sdim    Disk *disk;
830234353Sdim    Chunk *c1, *c2, *rootdev, *swapdev, *usrdev, *vardev;
831234353Sdim    Device **devs;
832234353Sdim    PartInfo *root;
833234353Sdim    char dname[80];
834234353Sdim    extern int MakeDevChunk(Chunk *c, char *n);
835234353Sdim    Boolean upgrade = FALSE;
836234353Sdim
837234353Sdim    /* If we've already done this, bail out */
838234353Sdim    if (!variable_cmp(DISK_LABELLED, "written"))
839234353Sdim	return DITEM_SUCCESS;
840234353Sdim
841234353Sdim    upgrade = !variable_cmp(SYSTEM_STATE, "upgrade");
842193323Sed    if (!checkLabels(TRUE, &rootdev, &swapdev, &usrdev, &vardev))
843193323Sed	return DITEM_FAILURE;
844202375Srdivacky
845234353Sdim    if (rootdev)
846234353Sdim	root = (PartInfo *)rootdev->private_data;
847234353Sdim    else
848234353Sdim	root = NULL;
849202375Srdivacky
850234353Sdim    command_clear();
851234353Sdim    if (swapdev && RunningAsInit) {
852234353Sdim	/* As the very first thing, try to get ourselves some swap space */
853234353Sdim	sprintf(dname, "/dev/%s", swapdev->name);
854193323Sed	if (!Fake && (!MakeDevChunk(swapdev, "/dev") || !file_readable(dname))) {
855234353Sdim	    msgConfirm("Unable to make device node for %s in /dev!\n"
856234353Sdim		       "The creation of filesystems will be aborted.", dname);
857234353Sdim	    return DITEM_FAILURE;
858234353Sdim	}
859193323Sed
860234353Sdim	if (!Fake) {
861234353Sdim	    if (!swapon(dname))
862234353Sdim		msgNotify("Added %s as initial swap device", dname);
863234353Sdim	    else
864234353Sdim		msgConfirm("WARNING!  Unable to swap to %s: %s\n"
865234353Sdim			   "This may cause the installation to fail at some point\n"
866234353Sdim			   "if you don't have a lot of memory.", dname, strerror(errno));
867234353Sdim	}
868234353Sdim    }
869234353Sdim
870234353Sdim    if (rootdev && RunningAsInit) {
871234353Sdim	/* Next, create and/or mount the root device */
872193323Sed	sprintf(dname, "/dev/r%s", rootdev->name);
873193323Sed	if (!Fake && (!MakeDevChunk(rootdev, "/dev") || !file_readable(dname))) {
874234353Sdim	    msgConfirm("Unable to make device node for %s in /dev!\n"
875234353Sdim		       "The creation of filesystems will be aborted.", dname);
876234353Sdim	    return DITEM_FAILURE;
877234353Sdim	}
878234353Sdim	if (strcmp(root->mountpoint, "/"))
879234353Sdim	    msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", rootdev->name, root->mountpoint);
880234353Sdim
881234353Sdim	if (root->newfs && (!upgrade || !msgYesNo("You are upgrading - are you SURE you want to newfs the root partition?"))) {
882234353Sdim	    int i;
883234353Sdim
884234353Sdim	    msgNotify("Making a new root filesystem on %s", dname);
885234353Sdim	    i = vsystem("%s %s", root->newfs_cmd, dname);
886234353Sdim	    if (i) {
887234353Sdim		msgConfirm("Unable to make new root filesystem on %s!\n"
888234353Sdim			   "Command returned status %d", dname, i);
889234353Sdim		return DITEM_FAILURE;
890234353Sdim	    }
891234353Sdim	}
892234353Sdim	else {
893234353Sdim	    if (!upgrade) {
894234353Sdim		msgConfirm("Warning:  Using existing root partition.  It will be assumed\n"
895234353Sdim			   "that you have the appropriate device entries already in /dev.");
896198090Srdivacky	    }
897202375Srdivacky	    msgNotify("Checking integrity of existing %s filesystem.", dname);
898234353Sdim	    i = vsystem("fsck -y %s", dname);
899234353Sdim	    if (i)
900234353Sdim		msgConfirm("Warning: fsck returned status of %d for %s.\n"
901234353Sdim			   "This partition may be unsafe to use.", i, dname);
902234353Sdim	}
903234353Sdim
904193323Sed	/* Switch to block device */
905202375Srdivacky	sprintf(dname, "/dev/%s", rootdev->name);
906234353Sdim	if (Mount("/mnt", dname)) {
907234353Sdim	    msgConfirm("Unable to mount the root file system on %s!  Giving up.", dname);
908234353Sdim	    return DITEM_FAILURE;
909234353Sdim	}
910234353Sdim    }
911234353Sdim
912224145Sdim    /* Now buzz through the rest of the partitions and mount them too */
913234353Sdim    devs = deviceFind(NULL, DEVICE_TYPE_DISK);
914234353Sdim    for (i = 0; devs[i]; i++) {
915234353Sdim	if (!devs[i]->enabled)
916234353Sdim	    continue;
917234353Sdim
918234353Sdim	disk = (Disk *)devs[i]->private;
919226633Sdim	if (!disk->chunks) {
920234353Sdim	    msgConfirm("No chunk list found for %s!", disk->name);
921234353Sdim	    return DITEM_FAILURE;
922234353Sdim	}
923234353Sdim	if (RunningAsInit && root && (root->newfs || upgrade)) {
924234353Sdim	    Mkdir("/mnt/dev");
925234353Sdim	    if (!Fake)
926224145Sdim		MakeDevDisk(disk, "/mnt/dev");
927224145Sdim	}
928224145Sdim	else if (!RunningAsInit && !Fake)
929234353Sdim	    MakeDevDisk(disk, "/dev");
930234353Sdim
931234353Sdim	for (c1 = disk->chunks->part; c1; c1 = c1->next) {
932234353Sdim	    if (c1->type == freebsd) {
933234353Sdim		for (c2 = c1->part; c2; c2 = c2->next) {
934193323Sed		    if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) {
935234353Sdim			PartInfo *tmp = (PartInfo *)c2->private_data;
936234353Sdim
937234353Sdim			/* Already did root */
938234353Sdim			if (c2 == rootdev)
939234353Sdim			    continue;
940234353Sdim
941234353Sdim			if (tmp->newfs && (!upgrade || !msgYesNo("You are upgradding - are you SURE you want to newfs /dev/%s?", c2->name)))
942234353Sdim			    command_shell_add(tmp->mountpoint, "%s %s/dev/r%s", tmp->newfs_cmd, RunningAsInit ? "/mnt" : "", c2->name);
943234353Sdim			else
944234353Sdim			    command_shell_add(tmp->mountpoint, "fsck -y %s/dev/r%s", RunningAsInit ? "/mnt" : "", c2->name);
945234353Sdim			command_func_add(tmp->mountpoint, Mount, c2->name);
946193323Sed		    }
947234353Sdim		    else if (c2->type == part && c2->subtype == FS_SWAP) {
948234353Sdim			char fname[80];
949234353Sdim			int i;
950234353Sdim
951234353Sdim			if (c2 == swapdev)
952234353Sdim			    continue;
953202375Srdivacky			sprintf(fname, "%s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name);
954234353Sdim			i = (Fake || swapon(fname));
955234353Sdim			if (!i)
956234353Sdim			    msgNotify("Added %s as an additional swap device", fname);
957234353Sdim			else
958234353Sdim			    msgConfirm("Unable to add %s as a swap device: %s", fname, strerror(errno));
959234353Sdim		    }
960224145Sdim		}
961193323Sed	    }
962234353Sdim	    else if (c1->type == fat && c1->private_data && (root->newfs || upgrade)) {
963234353Sdim		char name[FILENAME_MAX];
964234353Sdim
965224145Sdim		sprintf(name, "%s/%s", RunningAsInit ? "/mnt" : "", ((PartInfo *)c1->private_data)->mountpoint);
966234353Sdim		Mkdir(name);
967234353Sdim	    }
968234353Sdim	}
969234353Sdim    }
970234353Sdim
971234353Sdim    if (RunningAsInit) {
972234353Sdim	msgNotify("Copying initial device files..");
973234353Sdim	/* Copy the boot floppy's dev files */
974234353Sdim	if ((root->newfs || upgrade) && vsystem("find -x /dev | cpio %s -pdum /mnt", cpioVerbosity())) {
975234353Sdim	    msgConfirm("Couldn't clone the /dev files!");
976234353Sdim	    return DITEM_FAILURE;
977234353Sdim	}
978234353Sdim    }
979234353Sdim
980234353Sdim    command_sort();
981234353Sdim    command_execute();
982234353Sdim    return DITEM_SUCCESS;
983234353Sdim}
984234353Sdim
985234353Sdim/* Initialize various user-settable values to their defaults */
986234353Sdimint
987234353SdiminstallVarDefaults(dialogMenuItem *self)
988234353Sdim{
989234353Sdim    char *cp;
990234353Sdim
991234353Sdim    /* Set default startup options */
992234353Sdim    variable_set2(VAR_ROUTER_ENABLE,		"NO");
993193323Sed    variable_set2(VAR_RELNAME,			RELEASE_NAME);
994234353Sdim    variable_set2(VAR_CPIO_VERBOSITY,		"high");
995234353Sdim    variable_set2(VAR_TAPE_BLOCKSIZE,		DEFAULT_TAPE_BLOCKSIZE);
996234353Sdim    variable_set2(VAR_INSTALL_ROOT,		"/");
997234353Sdim    variable_set2(VAR_INSTALL_CFG,		"install.cfg");
998234353Sdim    cp = getenv("EDITOR");
999234353Sdim    if (!cp)
1000234353Sdim	cp = "/usr/bin/ee";
1001234353Sdim    variable_set2(VAR_EDITOR,			cp);
1002234353Sdim    variable_set2(VAR_FTP_USER,			"ftp");
1003234353Sdim    variable_set2(VAR_BROWSER_PACKAGE,		PACKAGE_LYNX);
1004234353Sdim    variable_set2(VAR_BROWSER_BINARY,		"/usr/local/bin/lynx");
1005234353Sdim    variable_set2(VAR_FTP_STATE,		"passive");
1006234353Sdim    variable_set2(VAR_NFS_SECURE,		"YES");
1007234353Sdim    variable_set2(VAR_PKG_TMPDIR,		"/usr/tmp");
1008234353Sdim    variable_set2(VAR_GATED_PKG,		PACKAGE_GATED);
1009234353Sdim    variable_set2(VAR_PCNFSD_PKG,		PACKAGE_PCNFSD);
1010234353Sdim    variable_set2(VAR_MEDIA_TIMEOUT,		itoa(MEDIA_TIMEOUT));
1011234353Sdim    if (getpid() != 1)
1012193323Sed	variable_set2(SYSTEM_STATE,		"update");
1013234353Sdim    else
1014234353Sdim	variable_set2(SYSTEM_STATE,		"init");
1015234353Sdim    return DITEM_SUCCESS;
1016234353Sdim}
1017234353Sdim
1018234353Sdim/* Load the environment up from various system configuration files */
1019234353Sdimvoid
1020234353SdiminstallEnvironment(void)
1021234353Sdim{
1022234353Sdim    if (file_readable("/etc/rc.conf"))
1023234353Sdim	configEnvironmentRC_conf("/etc/rc.conf");
1024234353Sdim    if (file_readable("/etc/resolv.conf"))
1025234353Sdim	configEnvironmentResolv("/etc/resolv.conf");
1026234353Sdim}
1027234353Sdim
1028234353Sdim/* Copy the boot floppy contents into /stand */
1029234353SdimBoolean
1030234353SdimcopySelf(void)
1031234353Sdim{
1032193323Sed    int i;
1033193323Sed
1034234353Sdim    if (file_readable("/boot.help"))
1035234353Sdim	vsystem("cp /boot.help /mnt");
1036234353Sdim    msgWeHaveOutput("Copying the boot floppy to /stand on root filesystem");
1037234353Sdim    i = vsystem("find -x /stand | cpio %s -pdum /mnt", cpioVerbosity());
1038234353Sdim    if (i) {
1039234353Sdim	msgConfirm("Copy returned error status of %d!", i);
1040234353Sdim	return FALSE;
1041193323Sed    }
1042193323Sed
1043234353Sdim    /* Copy the /etc files into their rightful place */
1044234353Sdim    if (vsystem("cd /mnt/stand; find etc | cpio %s -pdum /mnt", cpioVerbosity())) {
1045234353Sdim	msgConfirm("Couldn't copy up the /etc files!");
1046234353Sdim	return TRUE;
1047234353Sdim    }
1048234353Sdim    return TRUE;
1049234353Sdim}
1050234353Sdim
1051234353Sdimstatic void
1052234353Sdimcreate_termcap(void)
1053234353Sdim{
1054234353Sdim    FILE *fp;
1055234353Sdim
1056198090Srdivacky    const char *caps[] = {
1057234353Sdim	termcap_vt100, termcap_cons25, termcap_cons25_m, termcap_cons25r,
1058234353Sdim	termcap_cons25r_m, termcap_cons25l1, termcap_cons25l1_m, NULL,
1059234353Sdim    };
1060234353Sdim    const char **cp;
1061198090Srdivacky
1062234353Sdim    if (!file_readable(TERMCAP_FILE)) {
1063234353Sdim	Mkdir("/usr/share/misc");
1064234353Sdim	fp = fopen(TERMCAP_FILE, "w");
1065234353Sdim	if (!fp) {
1066218893Sdim	    msgConfirm("Unable to initialize termcap file. Some screen-oriented\nutilities may not work.");
1067198090Srdivacky	    return;
1068234353Sdim	}
1069234353Sdim	cp = caps;
1070234353Sdim	while (*cp)
1071234353Sdim	    fprintf(fp, "%s\n", *(cp++));
1072193323Sed	fclose(fp);
1073193323Sed    }
1074218893Sdim}
1075193323Sed
1076234353Sdim#ifdef SAVE_USERCONFIG
1077234353Sdimstatic void
1078234353Sdimsave_userconfig_to_kernel(char *kern)
1079193323Sed{
1080234353Sdim    struct kernel *core, *boot;
1081234353Sdim    struct list *c_isa, *b_isa, *c_dev, *b_dev;
1082234353Sdim    int i, d;
1083234353Sdim
1084234353Sdim    if ((core = uc_open("-incore")) == NULL) {
1085234353Sdim	msgDebug("save_userconf: Can't read in-core information for kernel.\n");
1086234353Sdim	return;
1087234353Sdim    }
1088193323Sed
1089234353Sdim    if ((boot = uc_open(kern)) == NULL) {
1090234353Sdim	msgDebug("save_userconf: Can't read device information for kernel image %s\n", kern);
1091234353Sdim	return;
1092239462Sdim    }
1093234353Sdim
1094263508Sdim    msgNotify("Saving any boot -c changes to new kernel...");
1095234353Sdim    c_isa = uc_getdev(core, "-isa");
1096234353Sdim    b_isa = uc_getdev(boot, "-isa");
1097234353Sdim    if (isDebug())
1098234353Sdim	msgDebug("save_userconf: got %d ISA device entries from core, %d from boot.\n", c_isa->ac, b_isa->ac);
1099234353Sdim    for (d = 0; d < c_isa->ac; d++) {
1100234353Sdim	if (isDebug())
1101234353Sdim	    msgDebug("save_userconf: ISA device loop, c_isa->av[%d] = %s\n", d, c_isa->av[d]);
1102234353Sdim	if (strcmp(c_isa->av[d], "npx0")) { /* special case npx0, which mucks with its id_irq member */
1103193323Sed	    c_dev = uc_getdev(core, c_isa->av[d]);
1104193323Sed	    b_dev = uc_getdev(boot, b_isa->av[d]);
1105193323Sed	    if (!c_dev || !b_dev) {
1106193323Sed		msgDebug("save_userconf: c_dev: %x b_dev: %x\n", c_dev, b_dev);
1107193323Sed		continue;
1108193323Sed	    }
1109226633Sdim	    if (isDebug())
1110226633Sdim		msgDebug("save_userconf: ISA device %s: %d config parameters (core), %d (boot)\n",
1111193323Sed			 c_isa->av[d], c_dev->ac, b_dev->ac);
1112193323Sed	    for (i = 0; i < c_dev->ac; i++) {
1113226633Sdim		if (isDebug())
1114193323Sed		    msgDebug("save_userconf: c_dev->av[%d] = %s, b_dev->av[%d] = %s\n", i, c_dev->av[i], i, b_dev->av[i]);
1115193323Sed		if (strcmp(c_dev->av[i], b_dev->av[i])) {
1116263508Sdim		    if (isDebug())
1117263508Sdim			msgDebug("save_userconf: %s (boot) -> %s (core)\n",
1118263508Sdim				 c_dev->av[i], b_dev->av[i]);
1119193323Sed		    isa_setdev(boot, c_dev);
1120193323Sed		}
1121193323Sed	    }
1122193323Sed	}
1123193323Sed	else {
1124193323Sed	    if (isDebug())
1125193323Sed		msgDebug("skipping npx0\n");
1126193323Sed	}
1127193323Sed    }
1128193323Sed    if (isDebug())
1129193323Sed	msgDebug("Closing kernels\n");
1130193323Sed    uc_close(core, 0);
1131193323Sed    uc_close(boot, 1);
1132193323Sed}
1133193323Sed#endif
1134193323Sed