]> CyberLeo.Net >> Repos - FreeBSD/releng/8.2.git/blob - usr.sbin/sysinstall/install.c
Copy stable/8 to releng/8.2 in preparation for FreeBSD-8.2 release.
[FreeBSD/releng/8.2.git] / usr.sbin / sysinstall / install.c
1 /*
2  * The new sysinstall program.
3  *
4  * This is probably the last program in the `sysinstall' line - the next
5  * generation being essentially a complete rewrite.
6  *
7  * $FreeBSD$
8  *
9  * Copyright (c) 1995
10  *      Jordan Hubbard.  All rights reserved.
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer,
17  *    verbatim and that no modifications are made prior to this
18  *    point in the file.
19  * 2. Redistributions in binary form must reproduce the above copyright
20  *    notice, this list of conditions and the following disclaimer in the
21  *    documentation and/or other materials provided with the distribution.
22  *
23  * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND
24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26  * ARE DISCLAIMED.  IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE
27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29  * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION)
30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33  * SUCH DAMAGE.
34  *
35  */
36
37 #include "sysinstall.h"
38 #include <ctype.h>
39 #include <sys/consio.h>
40 #include <sys/disklabel.h>
41 #include <sys/errno.h>
42 #include <sys/ioctl.h>
43 #include <sys/fcntl.h>
44 #include <sys/wait.h>
45 #include <sys/uio.h>
46 #include <sys/param.h>
47 #define MSDOSFS
48 #include <sys/mount.h>
49 #include <ufs/ufs/ufsmount.h>
50 #include <fs/msdosfs/msdosfsmount.h>
51 #undef MSDOSFS
52 #include <sys/stat.h>
53 #include <sys/sysctl.h>
54 #include <libdisk.h>
55 #include <limits.h>
56 #include <unistd.h>
57 #include <termios.h>
58
59 /* Hack for rsaref package add, which displays interactive license.
60  * Used by package.c
61  */
62 int _interactiveHack;
63 int FixItMode = 0;
64 int NCpus;
65
66 static void     create_termcap(void);
67 static void     fixit_common(void);
68 int             fixit_livefs_common(dialogMenuItem *self);
69
70 #define TERMCAP_FILE    "/usr/share/misc/termcap"
71
72 static void     installConfigure(void);
73
74 Boolean
75 checkLabels(Boolean whinge)
76 {
77     Device **devs;
78     Boolean status;
79     Disk *disk;
80     PartInfo *pi;
81     Chunk *c1, *c2;
82     int i;
83
84     /* Don't allow whinging if noWarn is set */
85     if (variable_get(VAR_NO_WARN))
86         whinge = FALSE;
87
88     status = TRUE;
89     HomeChunk = RootChunk = SwapChunk = NULL;
90     TmpChunk = UsrChunk = VarChunk = NULL;
91 #ifdef __ia64__
92     EfiChunk = NULL;
93 #endif
94
95     /* We don't need to worry about root/usr/swap if we're already multiuser */
96     if (!RunningAsInit)
97         return status;
98
99     devs = deviceFind(NULL, DEVICE_TYPE_DISK);
100     /* First verify that we have a root device */
101     for (i = 0; devs[i]; i++) {
102         if (!devs[i]->enabled)
103             continue;
104         disk = (Disk *)devs[i]->private;
105         msgDebug("Scanning disk %s for root filesystem\n", disk->name);
106         if (!disk->chunks)
107             msgFatal("No chunk list found for %s!", disk->name);
108         for (c1 = disk->chunks->part; c1; c1 = c1->next) {
109 #ifdef __ia64__
110             c2 = c1;
111 #elif defined(__powerpc__)
112             if (c1->type == apple) {
113                 for (c2 = c1->part; c2; c2 = c2->next) {
114 #else
115             if (c1->type == freebsd) {
116                 for (c2 = c1->part; c2; c2 = c2->next) {
117 #endif
118
119                     pi = (PartInfo *)c2->private_data;
120                     if (c2->type == part && c2->subtype != FS_SWAP && pi != NULL) {
121                         if (!strcmp(pi->mountpoint, "/")) {
122                             if (RootChunk) {
123                                 if (whinge)
124                                     msgConfirm("WARNING:  You have more than one root device set?!\n"
125                                                "Using the first one found.");
126                                 continue;
127                             }
128                             else {
129                                 RootChunk = c2;
130                                 if (isDebug())
131                                     msgDebug("Found rootdev at %s!\n", RootChunk->name);
132                             }
133                         }
134                         else if (!strcmp(pi->mountpoint, "/usr")) {
135                             if (UsrChunk) {
136                                 if (whinge)
137                                     msgConfirm("WARNING:  You have more than one /usr filesystem.\n"
138                                                "Using the first one found.");
139                                 continue;
140                             }
141                             else {
142                                 UsrChunk = c2;
143                                 if (isDebug())
144                                     msgDebug("Found usrdev at %s!\n", UsrChunk->name);
145                             }
146                         }
147                         else if (!strcmp(pi->mountpoint, "/var")) {
148                             if (VarChunk) {
149                                 if (whinge)
150                                     msgConfirm("WARNING:  You have more than one /var filesystem.\n"
151                                                "Using the first one found.");
152                                 continue;
153                             }
154                             else {
155                                 VarChunk = c2;
156                                 if (isDebug())
157                                     msgDebug("Found vardev at %s!\n", VarChunk->name);
158                             }
159                         } else if (!strcmp(pi->mountpoint, "/tmp")) {
160                             if (TmpChunk) {
161                                 if (whinge)
162                                     msgConfirm("WARNING:  You have more than one /tmp filesystem.\n"
163                                                "Using the first one found.");
164                                 continue;
165                             }
166                             else {
167                                 TmpChunk = c2;
168                                 if (isDebug())
169                                     msgDebug("Found tmpdev at %s!\n", TmpChunk->name);
170                             }
171                         } else if (!strcmp(pi->mountpoint, "/home")) {
172                             if (HomeChunk) {
173                                 if (whinge)
174                                     msgConfirm("WARNING:  You have more than one /home filesystem.\n"
175                                                "Using the first one found.");
176                                 continue;
177                             }
178                             else {
179                                 HomeChunk = c2;
180                                 if (isDebug())
181                                     msgDebug("Found homedev at %s!\n", HomeChunk->name);
182                             }
183                         }
184                     }
185 #ifndef __ia64__
186                 }
187             }
188 #endif
189         }
190     }
191
192     /* Now check for swap devices */
193     for (i = 0; devs[i]; i++) {
194         if (!devs[i]->enabled)
195             continue;
196         disk = (Disk *)devs[i]->private;
197         msgDebug("Scanning disk %s for swap partitions\n", disk->name);
198         if (!disk->chunks)
199             msgFatal("No chunk list found for %s!", disk->name);
200         for (c1 = disk->chunks->part; c1; c1 = c1->next) {
201
202 #ifdef __ia64__
203             c2 = c1;
204 #elif defined(__powerpc__)
205             if (c1->type == apple) {
206                 for (c2 = c1->part; c2; c2 = c2->next) {
207 #else
208             if (c1->type == freebsd) {
209                 for (c2 = c1->part; c2; c2 = c2->next) {
210 #endif
211                     if (c2->type == part && c2->subtype == FS_SWAP && !SwapChunk) {
212                         SwapChunk = c2;
213                         if (isDebug())
214                             msgDebug("Found swapdev at %s!\n", SwapChunk->name);
215                         break;
216                     }
217 #ifndef __ia64__
218                 }
219             }
220 #endif
221         }
222     }
223
224 #ifdef __ia64__
225     for (i = 0; devs[i] != NULL; i++) {
226         if (!devs[i]->enabled)
227             continue;
228         disk = (Disk *)devs[i]->private;
229         for (c1 = disk->chunks->part; c1 != NULL; c1 = c1->next) {
230                 pi = (PartInfo *)c1->private_data;
231             if (c1->type == efi && pi != NULL && pi->mountpoint[0] == '/')
232                 EfiChunk = c1;
233         }
234     }
235 #endif
236
237     if (!RootChunk && whinge) {
238         msgConfirm("No root device found - you must label a partition as /\n"
239                    "in the label editor.");
240         status = FALSE;
241     }
242     if (!SwapChunk && whinge) {
243         if (msgYesNo("No swap devices found - you should create at least one\n"
244                      "swap partition.  Without swap, the install will fail\n"
245                      "if you do not have enough RAM.  Continue anyway?"))
246             status = FALSE;
247     }
248 #ifdef __ia64__
249     if (EfiChunk == NULL && whinge) {
250         if (msgYesNo("No (mounted) EFI system partition found. Is this what you want?"))
251             status = FALSE;
252     }
253 #endif
254     return status;
255 }
256
257 static int
258 installInitial(void)
259 {
260     static Boolean alreadyDone = FALSE;
261     int status = DITEM_SUCCESS;
262
263     if (alreadyDone)
264         return DITEM_SUCCESS;
265
266     if (!variable_get(DISK_LABELLED)) {
267         msgConfirm("You need to assign disk labels before you can proceed with\n"
268                    "the installation.");
269         return DITEM_FAILURE;
270     }
271     /* If it's labelled, assume it's also partitioned */
272     if (!variable_get(DISK_PARTITIONED))
273         variable_set2(DISK_PARTITIONED, "yes", 0);
274
275     /* If we refuse to proceed, bail. */
276     dialog_clear_norefresh();
277     if (!variable_get(VAR_NO_WARN)) {
278         if (msgYesNo(
279             "Last Chance!  Are you SURE you want continue the installation?\n\n"
280             "If you're running this on a disk with data you wish to save\n"
281             "then WE STRONGLY ENCOURAGE YOU TO MAKE PROPER BACKUPS before\n"
282             "proceeding!\n\n"
283             "We can take no responsibility for lost disk contents!") != 0)
284         return DITEM_FAILURE;
285     }
286
287     if (DITEM_STATUS(diskLabelCommit(NULL)) != DITEM_SUCCESS) {
288         msgConfirm("Couldn't make filesystems properly.  Aborting.");
289         return DITEM_FAILURE;
290     }
291
292     if (!copySelf()) {
293         msgConfirm("installInitial: Couldn't clone the boot floppy onto the\n"
294                    "root file system.  Aborting!");
295         return DITEM_FAILURE;
296     }
297
298     if (!Restarting && chroot("/mnt") == -1) {
299         msgConfirm("installInitial: Unable to chroot to %s - this is bad!",
300                    "/mnt");
301         return DITEM_FAILURE;
302     }
303
304     chdir("/");
305     variable_set2(RUNNING_ON_ROOT, "yes", 0);
306
307     /* Configure various files in /etc */
308     if (DITEM_STATUS(configResolv(NULL)) == DITEM_FAILURE)
309         status = DITEM_FAILURE;
310     if (DITEM_STATUS(configFstab(NULL)) == DITEM_FAILURE)
311         status = DITEM_FAILURE;
312
313     /* stick a helpful shell over on the 4th VTY */
314     if (!variable_get(VAR_NO_HOLOSHELL))
315         systemCreateHoloshell();
316
317     alreadyDone = TRUE;
318     return status;
319 }
320
321 int
322 installFixitHoloShell(dialogMenuItem *self)
323 {
324     FixItMode = 1;
325     systemCreateHoloshell();
326     FixItMode = 0;
327     return DITEM_SUCCESS;
328 }
329
330 /*
331  * Load the live filesystem from USB media.
332  */
333 int
334 installFixitUSB(dialogMenuItem *self)
335 {
336         if (!RunningAsInit)
337                 return (DITEM_SUCCESS);
338
339         variable_set2(SYSTEM_STATE, "fixit", 0);
340
341         if (DITEM_STATUS(mediaSetUSB(NULL)) != DITEM_SUCCESS ||
342             !DEVICE_INIT(mediaDevice)) {
343                 msgConfirm("No USB devices found!");
344                 return (DITEM_FAILURE);
345         } else if (!file_readable("/dist/rescue/ldconfig")) {
346                 msgConfirm("Unable to find a FreeBSD live filesystem.");
347                 return (DITEM_FAILURE);
348         }
349
350         if (DITEM_STATUS(fixit_livefs_common(self)) == DITEM_FAILURE)
351                 return (DITEM_FAILURE);
352
353         mediaClose();
354         return (DITEM_SUCCESS);
355 }
356
357 int
358 installFixitCDROM(dialogMenuItem *self)
359 {
360     struct stat sb;
361     int need_eject;
362
363     if (!RunningAsInit)
364         return DITEM_SUCCESS;
365
366     variable_set2(SYSTEM_STATE, "fixit", 0);
367     need_eject = 0;
368     CDROMInitQuiet = 1;
369     while (1) {
370         if (need_eject)
371             msgConfirm(
372         "Please insert a FreeBSD live filesystem CD/DVD and press return");
373         if (DITEM_STATUS(mediaSetCDROM(NULL)) != DITEM_SUCCESS
374             || !DEVICE_INIT(mediaDevice)) {
375             /* If we can't initialize it, it's probably not a FreeBSD CDROM so punt on it */
376             mediaClose();
377             if (need_eject && msgYesNo("Unable to mount the disc. Do you want to try again?") != 0)
378                 return DITEM_FAILURE;
379         } else if (!file_readable("/dist/rescue/ldconfig")) {
380                 mediaClose();
381                 if (need_eject &&
382                     msgYesNo("Unable to find a FreeBSD live filesystem. Do you want to try again?") != 0)
383                     return DITEM_FAILURE;
384         } else
385             break;
386         CDROMInitQuiet = 0;
387         need_eject = 1;
388     }
389     CDROMInitQuiet = 0;
390
391     if (DITEM_STATUS(fixit_livefs_common(self)) == DITEM_FAILURE)
392         return (DITEM_FAILURE);
393
394     mediaClose();
395     if (need_eject)
396         msgConfirm("Please remove the FreeBSD fixit CDROM/DVD now.");
397     return DITEM_SUCCESS;
398 }
399
400 int
401 installFixitFloppy(dialogMenuItem *self)
402 {
403     struct ufs_args args;
404     extern char *distWanted;
405
406     if (!RunningAsInit)
407         return DITEM_SUCCESS;
408
409     /* Try to open the floppy drive */
410     if (DITEM_STATUS(mediaSetFloppy(NULL)) == DITEM_FAILURE || !mediaDevice) {
411         msgConfirm("Unable to set media device to floppy.");
412         mediaClose();
413         return DITEM_FAILURE;
414     }
415
416     memset(&args, 0, sizeof(args));
417     args.fspec = mediaDevice->devname;
418     mediaDevice->private = "/mnt2";
419     distWanted = NULL;
420     Mkdir("/mnt2");
421
422     variable_set2(SYSTEM_STATE, "fixit", 0);
423
424     while (1) {
425         if (!DEVICE_INIT(mediaDevice)) {
426             if (msgYesNo("The attempt to mount the fixit floppy failed, bad floppy\n"
427                          "or unclean filesystem.  Do you want to try again?"))
428                 return DITEM_FAILURE;
429         }
430         else
431             break;
432     }
433     if (!directory_exists("/tmp"))
434         (void)symlink("/mnt2/tmp", "/tmp");
435     fixit_common();
436     mediaClose();
437     msgConfirm("Please remove the fixit floppy now.");
438     return DITEM_SUCCESS;
439 }
440
441 /*
442  * The common code for both fixit variants.
443  */
444 static void
445 fixit_common(void)
446 {
447     pid_t child;
448     int waitstatus;
449
450     if (!directory_exists("/var/tmp/vi.recover")) {
451         if (DITEM_STATUS(Mkdir("/var/tmp/vi.recover")) != DITEM_SUCCESS) {
452             msgConfirm("Warning:  Was unable to create a /var/tmp/vi.recover directory.\n"
453                        "vi will kvetch and moan about it as a result but should still\n"
454                        "be essentially usable.");
455         }
456     }
457     if (!directory_exists("/bin"))
458         (void)Mkdir("/bin");
459     (void)symlink("/stand/sh", "/bin/sh");
460     /* Link the /etc/ files */
461     if (DITEM_STATUS(Mkdir("/etc")) != DITEM_SUCCESS)
462         msgConfirm("Unable to create an /etc directory!  Things are weird on this floppy..");
463     else if ((symlink("/mnt2/etc/spwd.db", "/etc/spwd.db") == -1 && errno != EEXIST) ||
464              (symlink("/mnt2/etc/protocols", "/etc/protocols") == -1 && errno != EEXIST) ||
465              (symlink("/mnt2/etc/group", "/etc/group") == -1 && errno != EEXIST) ||
466              (symlink("/mnt2/etc/services", "/etc/services") == -1 && errno != EEXIST))
467         msgConfirm("Couldn't symlink the /etc/ files!  I'm not sure I like this..");
468     if (!file_readable(TERMCAP_FILE))
469         create_termcap();
470     if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) 
471         systemSuspendDialog();  /* must be before the fork() */
472     if (!(child = fork())) {
473         int i, fd;
474         struct termios foo;
475         extern int login_tty(int);
476
477         ioctl(0, TIOCNOTTY, NULL);
478         for (i = getdtablesize(); i >= 0; --i)
479             close(i);
480
481         if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) 
482             fd = open("/dev/console", O_RDWR);
483         else
484             fd = open("/dev/ttyv3", O_RDWR);
485         ioctl(0, TIOCSCTTY, &fd);
486         dup2(0, 1);
487         dup2(0, 2);
488         DebugFD = 2;
489         if (login_tty(fd) == -1)
490             msgDebug("fixit: I can't set the controlling terminal.\n");
491
492         signal(SIGTTOU, SIG_IGN);
493         if (tcgetattr(0, &foo) != -1) {
494             foo.c_cc[VERASE] = '\010';
495             if (tcsetattr(0, TCSANOW, &foo) == -1)
496                 msgDebug("fixit shell: Unable to set erase character.\n");
497         }
498         else
499             msgDebug("fixit shell: Unable to get terminal attributes!\n");
500         setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/stand:"
501                "/mnt2/stand:/mnt2/bin:/mnt2/sbin:/mnt2/usr/bin:/mnt2/usr/sbin", 1);
502         if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) {
503             printf("Waiting for fixit shell to exit.\n"
504                 "When you are done, type ``exit'' to exit\n"
505                 "the fixit shell and be returned here.\n\n");
506             fflush(stdout);
507         } else {
508             ioctl(fd, VT_ACTIVATE, 0);
509         }
510
511         /* use the .profile from the fixit medium */
512         setenv("HOME", "/mnt2", 1);
513         chdir("/mnt2");
514         execlp("sh", "-sh", (char *)0);
515         msgDebug("fixit shell: Failed to execute shell!\n");
516         _exit(1);;
517     }
518     else {
519         if (strcmp(variable_get(VAR_FIXIT_TTY), "standard") == 0) {
520             dialog_clear_norefresh();
521             msgNotify("Waiting for fixit shell to exit.  Go to VTY4 now by\n"
522                 "typing ALT-F4.  When you are done, type ``exit'' to exit\n"
523                 "the fixit shell and be returned here.\n");
524         }
525         (void)waitpid(child, &waitstatus, 0);
526         if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0)
527             systemResumeDialog();
528         else if (OnVTY) {
529             ioctl(0, VT_ACTIVATE, 0);
530             msgInfo(NULL);
531         }
532     }
533     dialog_clear();
534 }
535
536 /*
537  * Some path/lib setup is required for the livefs fixit image. Since there's
538  * more than one media type for livefs now, this has been broken off into it's
539  * own function.
540  */
541 int
542 fixit_livefs_common(dialogMenuItem *self)
543 {
544         struct stat sb;
545
546         /*
547          * USB and CDROM media get mounted to /dist, but fixit code looks in
548          * /mnt2.
549          */
550         unlink("/mnt2");
551         rmdir("/mnt2");
552
553         if (symlink("/dist", "/mnt2")) {
554                 msgConfirm("Unable to symlink /mnt2 to the disc mount point.");
555                 return (DITEM_FAILURE);
556         }
557
558         /*
559          * If /tmp points to /mnt2/tmp from a previous fixit floppy session,
560          * recreate it.
561          */
562         if (lstat("/tmp", &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFLNK)
563                 unlink("/tmp");
564         Mkdir("/tmp");
565
566         /* Generate a new ld.so.hints */
567         if (!file_readable("/var/run/ld.so.hints")) {
568                 Mkdir("/var/run");
569                 if (vsystem("/mnt2/rescue/ldconfig -s /mnt2/lib "
570                     "/mnt2/usr/lib")) {
571                         msgConfirm("Warning: ldconfig could not create the "
572                             "ld.so hints file.\nDynamic executables from the "
573                             "disc likely won't work.");
574                 }
575         }
576
577         /* Create required libexec symlinks. */
578         Mkdir("/libexec");
579         if (!file_readable("/libexec/ld.so") &&
580             file_readable("/mnt2/libexec/ld.so")) {
581                 if (symlink("/mnt2/libexec/ld.so", "/libexec/ld.so"))
582                         msgDebug("Couldn't link to ld.so\n");
583         }
584
585         if (!file_readable("/libexec/ld-elf.so.1")) {
586                 if (symlink("/mnt2/libexec/ld-elf.so.1",
587                     "/libexec/ld-elf.so.1")) {
588                         msgConfirm("Warning: could not create the symlink for "
589                             "ld-elf.so.1\nDynamic executables from the disc "
590                             "likely won't work.");
591                 }
592         }
593
594         /* $PATH doesn't include /mnt2 by default. Create convenient symlink. */
595         if (!file_readable("/usr/bin/vi"))
596                 symlink("/mnt2/usr/bin/vi", "/usr/bin/vi");
597
598         /* Shared code used by all fixit types. */
599         fixit_common();
600
601         return (DITEM_SUCCESS);
602 }
603
604 int
605 installExpress(dialogMenuItem *self)
606 {
607     int i;
608
609     dialog_clear_norefresh();
610     variable_set2(SYSTEM_STATE, "express", 0);
611 #ifdef WITH_SLICES
612     if (DITEM_STATUS((i = diskPartitionEditor(self))) == DITEM_FAILURE)
613         return i;
614 #endif
615     
616     if (DITEM_STATUS((i = diskLabelEditor(self))) == DITEM_FAILURE)
617         return i;
618
619     if (DITEM_STATUS((i = installCommit(self))) == DITEM_SUCCESS) {
620         i |= DITEM_LEAVE_MENU;
621
622         /* Give user the option of one last configuration spree */
623         installConfigure();
624     }
625     return i;
626 }
627
628 /* Standard mode installation */
629 int
630 installStandard(dialogMenuItem *self)
631 {
632     int i, tries = 0;
633     Device **devs;
634
635     variable_set2(SYSTEM_STATE, "standard", 0);
636     dialog_clear_norefresh();
637 #ifdef WITH_SLICES
638     msgConfirm("In the next menu, you will need to set up a DOS-style (\"fdisk\") partitioning\n"
639                "scheme for your hard disk.  If you simply wish to devote all disk space\n"
640                "to FreeBSD (overwriting anything else that might be on the disk(s) selected)\n"
641                "then use the (A)ll command to select the default partitioning scheme followed\n"
642                "by a (Q)uit.  If you wish to allocate only free space to FreeBSD, move to a\n"
643                "partition marked \"unused\" and use the (C)reate command.");
644
645 nodisks:
646     if (DITEM_STATUS(diskPartitionEditor(self)) == DITEM_FAILURE)
647         return DITEM_FAILURE;
648
649     if (diskGetSelectCount(&devs) <= 0 && tries < 3) {
650         msgConfirm("You need to select some disks to operate on!  Be sure to use SPACE\n"
651                    "instead of RETURN in the disk selection menu when selecting a disk.");
652         ++tries;
653         goto nodisks;
654     }
655
656     msgConfirm("Now you need to create BSD partitions inside of the fdisk partition(s)\n"
657                "just created.  If you have a reasonable amount of disk space (1GB or more)\n"
658                "and don't have any special requirements, simply use the (A)uto command to\n"
659                "allocate space automatically.  If you have more specific needs or just don't\n"
660                "care for the layout chosen by (A)uto, press F1 for more information on\n"
661                "manual layout.");
662 #else
663     msgConfirm("First you need to create BSD partitions on the disk which you are\n"
664                "installing to.  If you have a reasonable amount of disk space (1GB or more)\n"
665                "and don't have any special requirements, simply use the (A)uto command to\n"
666                "allocate space automatically.  If you have more specific needs or just don't\n"
667                "care for the layout chosen by (A)uto, press F1 for more information on\n"
668                "manual layout.");
669 #endif
670
671     if (DITEM_STATUS(diskLabelEditor(self)) == DITEM_FAILURE)
672         return DITEM_FAILURE;
673
674     if (DITEM_STATUS((i = installCommit(self))) == DITEM_FAILURE) {
675         dialog_clear();
676         msgConfirm("Installation completed with some errors.  You may wish to\n"
677                    "scroll through the debugging messages on VTY1 with the\n"
678                    "scroll-lock feature.  You can also choose \"No\" at the next\n"
679                    "prompt and reboot and try the installation again.");
680         return i;
681
682     }
683     else {
684         dialog_clear();
685         msgConfirm("Congratulations!  You now have FreeBSD installed on your system.\n\n"
686                    "We will now move on to the final configuration questions.\n"
687                    "For any option you do not wish to configure, simply select\n"
688                    "No.\n\n"
689                    "If you wish to re-enter this utility after the system is up, you\n"
690                    "may do so by typing: /usr/sbin/sysinstall.");
691     }
692     if (mediaDevice->type != DEVICE_TYPE_FTP && mediaDevice->type != DEVICE_TYPE_NFS) {
693         if (!msgYesNo("Would you like to configure any Ethernet network devices?")) {
694             Device *tmp = tcpDeviceSelect();
695
696             if (tmp && !((DevInfo *)tmp->private)->use_dhcp && !msgYesNo("Would you like to bring the %s interface up right now?", tmp->name))
697                 if (!DEVICE_INIT(tmp))
698                     msgConfirm("Initialization of %s device failed.", tmp->name);
699         }
700         dialog_clear_norefresh();
701     }
702
703     if (!msgNoYes("Do you want this machine to function as a network gateway?"))
704         variable_set2("gateway_enable", "YES", 1);
705
706     dialog_clear_norefresh();
707     if (!msgNoYes("Do you want to configure inetd and the network services that it provides?"))
708         configInetd(self);
709
710     dialog_clear_norefresh();
711     if (!msgNoYes("Would you like to enable SSH login?"))
712         variable_set2("sshd_enable", "YES", 1);
713
714     dialog_clear_norefresh();
715     if (!msgNoYes("Do you want to have anonymous FTP access to this machine?"))
716         configAnonFTP(self);
717
718     dialog_clear_norefresh();
719     if (!msgNoYes("Do you want to configure this machine as an NFS server?"))
720         configNFSServer(self);
721
722     dialog_clear_norefresh();
723     if (!msgNoYes("Do you want to configure this machine as an NFS client?"))
724         variable_set2("nfs_client_enable", "YES", 1);
725
726 #ifdef WITH_SYSCONS
727     dialog_clear_norefresh();
728     if (!msgNoYes("Would you like to customize your system console settings?"))
729         dmenuOpenSimple(&MenuSyscons, FALSE);
730 #endif
731
732     dialog_clear_norefresh();
733     if (!msgYesNo("Would you like to set this machine's time zone now?"))
734         systemExecute("tzsetup");
735
736 #ifdef WITH_MICE
737     dialog_clear_norefresh();
738     if (!msgNoYes("Does this system have a PS/2, serial, or bus mouse?"))
739         dmenuOpenSimple(&MenuMouse, FALSE);
740 #endif
741
742 #ifdef __i386__
743     if (checkLoaderACPI() != 0) {
744         dialog_clear_norefresh();
745         if (!msgNoYes("ACPI was disabled during boot.\n"
746                       "Would you like to disable it permanently?"))
747                 (void)configLoaderACPI(1 /*disable*/);
748     }
749 #endif
750
751     /* Now would be a good time to checkpoint the configuration data */
752     configRC_conf();
753     sync();
754
755     dialog_clear_norefresh();
756     if (!msgYesNo("The FreeBSD package collection is a collection of thousands of ready-to-run\n"
757                   "applications, from text editors to games to Web servers and more.  Would you\n"
758                   "like to browse the collection now?")) {
759         (void)configPackages(self);
760     }
761
762     if (!msgYesNo("Would you like to add any initial user accounts to the system?\n"
763                   "Adding at least one account for yourself at this stage is suggested\n"
764                   "since working as the \"root\" user is dangerous (it is easy to do\n"
765                   "things which adversely affect the entire system)."))
766         (void)configUsers(self);
767
768     msgConfirm("Now you must set the system manager's password.\n"
769                "This is the password you'll use to log in as \"root\".");
770     if (!systemExecute("passwd root"))
771         variable_set2("root_password", "YES", 0);
772
773     /* XXX Put whatever other nice configuration questions you'd like to ask the user here XXX */
774
775     /* Give user the option of one last configuration spree */
776     dialog_clear_norefresh();
777     installConfigure();
778     return DITEM_LEAVE_MENU;
779 }
780
781 /* The version of commit we call from the Install Custom menu */
782 int
783 installCustomCommit(dialogMenuItem *self)
784 {
785     int i;
786
787     i = installCommit(self);
788     if (DITEM_STATUS(i) == DITEM_SUCCESS) {
789         /* Give user the option of one last configuration spree */
790         installConfigure();
791         return i;
792     }
793     else
794         msgConfirm("The commit operation completed with errors.  Not\n"
795                    "updating /etc files.");
796     return i;
797 }
798
799 /*
800  * What happens when we finally decide to going ahead with the installation.
801  *
802  * This is broken into multiple stages so that the user can do a full
803  * installation but come back here again to load more distributions,
804  * perhaps from a different media type.  This would allow, for
805  * example, the user to load the majority of the system from CDROM and
806  * then use ftp to load a different dist.
807  */
808 int
809 installCommit(dialogMenuItem *self)
810 {
811     int i;
812     char *str;
813
814     dialog_clear_norefresh();
815     if (!Dists)
816         distConfig(NULL);
817
818     if (!Dists) {
819         (void)dmenuOpenSimple(&MenuDistributions, FALSE);
820         /* select reasonable defaults if necessary */
821         if (!Dists)
822             Dists = _DIST_USER;
823         if (!KernelDists)
824             KernelDists = selectKernel();
825     }
826
827     if (!mediaVerify())
828         return DITEM_FAILURE;
829
830     str = variable_get(SYSTEM_STATE);
831     if (isDebug())
832         msgDebug("installCommit: System state is `%s'\n", str);
833
834     /* Installation stuff we wouldn't do to a running system */
835     if (RunningAsInit && DITEM_STATUS((i = installInitial())) == DITEM_FAILURE)
836         return i;
837
838 try_media:
839     if (!DEVICE_INIT(mediaDevice)) {
840         if (!msgYesNo("Unable to initialize selected media. Would you like to\n"
841                       "adjust your media configuration and try again?")) {
842             mediaDevice = NULL;
843             if (!mediaVerify())
844                 return DITEM_FAILURE;
845             else
846                 goto try_media;
847         }
848         else
849             return DITEM_FAILURE;
850     }
851
852     /* Now go get it all */
853     i = distExtractAll(self);
854
855     if (i == FALSE)
856             return DITEM_FAILURE;
857
858     /* When running as init, *now* it's safe to grab the rc.foo vars */
859     installEnvironment();
860
861     variable_set2(SYSTEM_STATE, DITEM_STATUS(i) == DITEM_FAILURE ? "error-install" : "full-install", 0);
862
863     return i;
864 }
865
866 static void
867 installConfigure(void)
868 {
869     /* Final menu of last resort */
870     if (!msgNoYes("Visit the general configuration menu for a chance to set\n"
871                   "any last options?"))
872         dmenuOpenSimple(&MenuConfigure, FALSE);
873     configRC_conf();
874     sync();
875 }
876
877 int
878 installFixupBase(dialogMenuItem *self)
879 {
880     FILE *orig, *new;
881     char buf[1024];
882     char *pos;
883     FILE *fp;
884 #ifdef __ia64__
885     const char *efi_mntpt;
886 #endif
887
888     /* All of this is done only as init, just to be safe */
889     if (RunningAsInit) {
890 #if defined(__i386__) || defined(__amd64__)
891         if ((fp = fopen("/boot/loader.conf", "a")) != NULL) {
892             if (!OnVTY) {
893                 fprintf(fp, "# -- sysinstall generated deltas -- #\n");
894                 fprintf(fp, "console=\"comconsole\"\n");
895             }
896             fclose(fp);
897         }
898 #endif
899
900         /* Fixup /etc/ttys to start a getty on the serial port.
901           This way after a serial installation you can login via
902           the serial port */
903
904         if (!OnVTY){
905             if (((orig=fopen("/etc/ttys","r")) != NULL) &&
906                 ((new=fopen("/etc/ttys.tmp","w")) != NULL)) {
907                 while (fgets(buf,sizeof(buf),orig)){
908                     if (strstr(buf,"ttyu0")){
909                         if ((pos=strstr(buf,"off"))){
910                             *pos++='o';
911                             *pos++='n';
912                             *pos++=' ';
913                         }
914                     }
915                     fputs(buf,new);
916                 }
917                 fclose(orig);
918                 fclose(new);
919
920                 rename("/etc/ttys.tmp","/etc/ttys");
921                 unlink("/etc/ttys.tmp");
922             }
923         }
924
925         
926         /* BOGON #2: We leave /etc in a bad state */
927         chmod("/etc", 0755);
928         
929         /* BOGON #3: No /var/db/mountdtab complains */
930         Mkdir("/var/db");
931         creat("/var/db/mountdtab", 0644);
932         
933         /* BOGON #4: /compat created by default in root fs */
934         Mkdir("/usr/compat");
935         vsystem("ln -s usr/compat /compat");
936
937         /* BOGON #5: aliases database not built for bin */
938         vsystem("newaliases");
939
940         /* BOGON #6: Remove /stand (finally) */
941         vsystem("rm -rf /stand");
942
943         /* Now run all the mtree stuff to fix things up */
944         vsystem("mtree -deU -f /etc/mtree/BSD.root.dist -p /");
945         vsystem("mtree -deU -f /etc/mtree/BSD.var.dist -p /var");
946         vsystem("mtree -deU -f /etc/mtree/BSD.usr.dist -p /usr");
947
948 #ifdef __ia64__
949         /* Move /boot to the the EFI partition and make /boot a link to it. */
950         efi_mntpt = (EfiChunk != NULL) ? ((PartInfo *)EfiChunk->private_data)->mountpoint : NULL;
951         if (efi_mntpt != NULL) {
952                 vsystem("if [ ! -L /boot ]; then mv /boot %s; fi", efi_mntpt);
953                 vsystem("if [ ! -e /boot ]; then ln -sf %s/boot /boot; fi",
954                     efi_mntpt + 1);     /* Skip leading '/' */
955                 /* Make sure the kernel knows which partition is the root file system. */
956                 vsystem("echo 'vfs.root.mountfrom=\"ufs:/dev/%s\"' >> /boot/loader.conf", RootChunk->name);
957         }
958 #endif
959
960         /* Do all the last ugly work-arounds here */
961     }
962     return DITEM_SUCCESS | DITEM_RESTORE;
963 }
964
965 int
966 installFixupKernel(dialogMenuItem *self, int dists)
967 {
968
969     /* All of this is done only as init, just to be safe */
970     if (RunningAsInit) {
971         /*
972          * Install something as /boot/kernel.  Prefer SMP
973          * over GENERIC--this should handle the case where
974          * both SMP and GENERIC are installed (otherwise we
975          * select the one kernel that was installed).
976          *
977          * NB: we assume any existing kernel has been saved
978          *     already and the /boot/kernel we remove is empty.
979          */
980         vsystem("rm -rf /boot/kernel");
981 #if WITH_SMP
982         if (dists & DIST_KERNEL_SMP)
983                 vsystem("mv /boot/SMP /boot/kernel");
984         else
985 #endif
986                 vsystem("mv /boot/GENERIC /boot/kernel");
987     }
988     return DITEM_SUCCESS | DITEM_RESTORE;
989 }
990
991 #define QUEUE_YES       1
992 #define QUEUE_NO        0
993 static int
994 performNewfs(PartInfo *pi, char *dname, int queue)
995 {
996         char buffer[LINE_MAX];
997
998         if (pi->do_newfs) {
999                 switch(pi->newfs_type) {
1000                 case NEWFS_UFS:
1001                         snprintf(buffer, LINE_MAX, "%s %s %s %s %s",
1002                             NEWFS_UFS_CMD,
1003                             pi->newfs_data.newfs_ufs.softupdates ?  "-U" : "",
1004                             pi->newfs_data.newfs_ufs.ufs1 ? "-O1" : "-O2",
1005                             pi->newfs_data.newfs_ufs.user_options,
1006                             dname);
1007                         break;
1008
1009                 case NEWFS_MSDOS:
1010                         snprintf(buffer, LINE_MAX, "%s %s", NEWFS_MSDOS_CMD,
1011                             dname);
1012                         break;
1013
1014                 case NEWFS_CUSTOM:
1015                         snprintf(buffer, LINE_MAX, "%s %s",
1016                             pi->newfs_data.newfs_custom.command, dname);
1017                         break;
1018                 }
1019
1020                 if (queue == QUEUE_YES) {
1021                         command_shell_add(pi->mountpoint, buffer);
1022                         return (0);
1023                 } else
1024                         return (vsystem(buffer));
1025         }
1026         return (0);
1027 }
1028
1029 /* Go newfs and/or mount all the filesystems we've been asked to */
1030 int
1031 installFilesystems(dialogMenuItem *self)
1032 {
1033     int i;
1034     Disk *disk;
1035     Chunk *c1, *c2;
1036     Device **devs;
1037     PartInfo *root;
1038     char dname[80];
1039     Boolean upgrade = FALSE;
1040
1041     /* If we've already done this, bail out */
1042     if (!variable_cmp(DISK_LABELLED, "written"))
1043         return DITEM_SUCCESS;
1044
1045     upgrade = !variable_cmp(SYSTEM_STATE, "upgrade");
1046     if (!checkLabels(TRUE))
1047         return DITEM_FAILURE;
1048
1049     root = (RootChunk != NULL) ? (PartInfo *)RootChunk->private_data : NULL;
1050
1051     command_clear();
1052     if (SwapChunk && RunningAsInit) {
1053         /* As the very first thing, try to get ourselves some swap space */
1054         sprintf(dname, "/dev/%s", SwapChunk->name);
1055         if (!Fake && !file_readable(dname)) {
1056             msgConfirm("Unable to find device node for %s in /dev!\n"
1057                        "The creation of filesystems will be aborted.", dname);
1058             return DITEM_FAILURE;
1059         }
1060
1061         if (!Fake) {
1062             if (!swapon(dname)) {
1063                 dialog_clear_norefresh();
1064                 msgNotify("Added %s as initial swap device", dname);
1065             }
1066             else {
1067                 msgConfirm("WARNING!  Unable to swap to %s: %s\n"
1068                            "This may cause the installation to fail at some point\n"
1069                            "if you don't have a lot of memory.", dname, strerror(errno));
1070             }
1071         }
1072     }
1073
1074     if (RootChunk && RunningAsInit) {
1075         /* Next, create and/or mount the root device */
1076         sprintf(dname, "/dev/%s", RootChunk->name);
1077         if (!Fake && !file_readable(dname)) {
1078             msgConfirm("Unable to make device node for %s in /dev!\n"
1079                        "The creation of filesystems will be aborted.", dname);
1080             return DITEM_FAILURE | DITEM_RESTORE;
1081         }
1082         if (strcmp(root->mountpoint, "/"))
1083             msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", RootChunk->name, root->mountpoint);
1084
1085         if (root->do_newfs && (!upgrade ||
1086             !msgNoYes("You are upgrading - are you SURE you want to newfs "
1087             "the root partition?"))) {
1088             int i;
1089
1090             dialog_clear_norefresh();
1091             msgNotify("Making a new root filesystem on %s", dname);
1092             i = performNewfs(root, dname, QUEUE_NO);
1093             if (i) {
1094                 msgConfirm("Unable to make new root filesystem on %s!\n"
1095                            "Command returned status %d", dname, i);
1096                 return DITEM_FAILURE | DITEM_RESTORE;
1097             }
1098         }
1099         else {
1100             if (!upgrade) {
1101                 msgConfirm("Warning:  Using existing root partition.");
1102             }
1103             dialog_clear_norefresh();
1104             msgNotify("Checking integrity of existing %s filesystem.", dname);
1105             i = vsystem("fsck_ffs -y %s", dname);
1106             if (i)
1107                 msgConfirm("Warning: fsck returned status of %d for %s.\n"
1108                            "This partition may be unsafe to use.", i, dname);
1109         }
1110
1111         /*
1112          * If soft updates was enabled in the editor but we didn't newfs,
1113          * use tunefs to update the soft updates flag on the file system.
1114          */
1115         if (!root->do_newfs && root->newfs_type == NEWFS_UFS &&
1116             root->newfs_data.newfs_ufs.softupdates) {
1117                 i = vsystem("tunefs -n enable %s", dname);
1118                 if (i)
1119                         msgConfirm("Warning: Unable to enable soft updates"
1120                             " for root file system on %s", dname);
1121         }
1122
1123         /* Switch to block device */
1124         sprintf(dname, "/dev/%s", RootChunk->name);
1125         if (Mount("/mnt", dname)) {
1126             msgConfirm("Unable to mount the root file system on %s!  Giving up.", dname);
1127             return DITEM_FAILURE | DITEM_RESTORE;
1128         }
1129
1130         /* Mount devfs for other partitions to mount */
1131         Mkdir("/mnt/dev");
1132         if (!Fake) {
1133             struct iovec iov[4];
1134
1135             iov[0].iov_base = "fstype";
1136             iov[0].iov_len = strlen(iov[0].iov_base) + 1;
1137             iov[1].iov_base = "devfs";
1138             iov[1].iov_len = strlen(iov[1].iov_base) + 1;
1139             iov[2].iov_base = "fspath";
1140             iov[2].iov_len = strlen(iov[2].iov_base) + 1;
1141             iov[3].iov_base = "/mnt/dev";
1142             iov[3].iov_len = strlen(iov[3].iov_base) + 1;
1143             i = nmount(iov, 4, 0);
1144
1145             if (i) {
1146                 dialog_clear_norefresh();
1147                 msgConfirm("Unable to mount DEVFS (error %d)", errno);
1148                 return DITEM_FAILURE | DITEM_RESTORE;
1149             }
1150         }
1151     }
1152
1153     /* Now buzz through the rest of the partitions and mount them too */
1154     devs = deviceFind(NULL, DEVICE_TYPE_DISK);
1155     for (i = 0; devs[i]; i++) {
1156         if (!devs[i]->enabled)
1157             continue;
1158
1159         disk = (Disk *)devs[i]->private;
1160         if (!disk->chunks) {
1161             msgConfirm("No chunk list found for %s!", disk->name);
1162             return DITEM_FAILURE | DITEM_RESTORE;
1163         }
1164         for (c1 = disk->chunks->part; c1; c1 = c1->next) {
1165 #ifdef __ia64__
1166         if (c1->type == part) {
1167                 c2 = c1;
1168                 {
1169 #elif defined(__powerpc__)
1170             if (c1->type == apple) {
1171                 for (c2 = c1->part; c2; c2 = c2->next) {
1172 #else
1173             if (c1->type == freebsd) {
1174                 for (c2 = c1->part; c2; c2 = c2->next) {
1175 #endif
1176                     if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) {
1177                         PartInfo *tmp = (PartInfo *)c2->private_data;
1178
1179                         /* Already did root */
1180                         if (c2 == RootChunk)
1181                             continue;
1182
1183                         sprintf(dname, "%s/dev/%s",
1184                             RunningAsInit ? "/mnt" : "", c2->name);
1185
1186                         if (tmp->do_newfs && (!upgrade ||
1187                             !msgNoYes("You are upgrading - are you SURE you"
1188                             " want to newfs /dev/%s?", c2->name)))
1189                                 performNewfs(tmp, dname, QUEUE_YES);
1190                         else
1191                             command_shell_add(tmp->mountpoint,
1192                                 "fsck_ffs -y %s/dev/%s", RunningAsInit ?
1193                                 "/mnt" : "", c2->name);
1194 #if 0
1195                         if (tmp->soft)
1196                             command_shell_add(tmp->mountpoint,
1197                             "tunefs -n enable %s/dev/%s", RunningAsInit ?
1198                             "/mnt" : "", c2->name);
1199 #endif
1200                         command_func_add(tmp->mountpoint, Mount, c2->name);
1201                     }
1202                     else if (c2->type == part && c2->subtype == FS_SWAP) {
1203                         char fname[80];
1204                         int i;
1205
1206                         if (c2 == SwapChunk)
1207                             continue;
1208                         sprintf(fname, "%s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name);
1209                         i = (Fake || swapon(fname));
1210                         if (!i) {
1211                             dialog_clear_norefresh();
1212                             msgNotify("Added %s as an additional swap device", fname);
1213                         }
1214                         else {
1215                             msgConfirm("Unable to add %s as a swap device: %s", fname, strerror(errno));
1216                         }
1217                     }
1218                 }
1219             }
1220             else if (c1->type == fat && c1->private_data &&
1221                 (root->do_newfs || upgrade)) {
1222                 char name[FILENAME_MAX];
1223
1224                 sprintf(name, "%s/%s", RunningAsInit ? "/mnt" : "", ((PartInfo *)c1->private_data)->mountpoint);
1225                 Mkdir(name);
1226             }
1227 #if defined(__ia64__)
1228             else if (c1->type == efi && c1->private_data) {
1229                 char bootdir[FILENAME_MAX];
1230                 PartInfo *pi = (PartInfo *)c1->private_data;
1231                 char *p;
1232
1233                 sprintf(dname, "%s/dev/%s", RunningAsInit ? "/mnt" : "",
1234                     c1->name);
1235
1236                 if (pi->do_newfs && (!upgrade ||
1237                     !msgNoYes("You are upgrading - are you SURE you want to "
1238                     "newfs /dev/%s?", c1->name)))
1239                         performNewfs(pi, dname, QUEUE_YES);
1240
1241                 command_func_add(pi->mountpoint, Mount_msdosfs, c1->name);
1242             }
1243 #endif
1244         }
1245     }
1246
1247     command_sort();
1248     command_execute();
1249     dialog_clear_norefresh();
1250     return DITEM_SUCCESS | DITEM_RESTORE;
1251 }
1252
1253 /* Initialize various user-settable values to their defaults */
1254 int
1255 installVarDefaults(dialogMenuItem *self)
1256 {
1257     char *cp, ncpus[10];
1258
1259     /* Set default startup options */
1260     cp = getsysctlbyname("kern.osrelease");
1261     variable_set2(VAR_RELNAME,                  cp, 0);
1262     free(cp);
1263     variable_set2(VAR_CPIO_VERBOSITY,           "high", 0);
1264     variable_set2(VAR_INSTALL_ROOT,             "/", 0);
1265     variable_set2(VAR_INSTALL_CFG,              "install.cfg", 0);
1266     cp = getenv("EDITOR");
1267     if (!cp)
1268         cp = "/usr/bin/ee";
1269     variable_set2(VAR_EDITOR,                   cp, 0);
1270     variable_set2(VAR_FTP_USER,                 "ftp", 0);
1271     variable_set2(VAR_BROWSER_PACKAGE,          "links", 0);
1272     variable_set2(VAR_BROWSER_BINARY,           "/usr/local/bin/links", 0);
1273     variable_set2(VAR_FTP_STATE,                "passive", 0);
1274     variable_set2(VAR_NFS_SECURE,               "NO", -1);
1275     variable_set2(VAR_NFS_TCP,                  "NO", -1);
1276     variable_set2(VAR_NFS_V3,                   "YES", -1);
1277     if (OnVTY)
1278             variable_set2(VAR_FIXIT_TTY,                "standard", 0);
1279     else
1280             variable_set2(VAR_FIXIT_TTY,                "serial", 0);
1281     variable_set2(VAR_PKG_TMPDIR,               "/var/tmp", 0);
1282     variable_set2(VAR_MEDIA_TIMEOUT,            itoa(MEDIA_TIMEOUT), 0);
1283     if (getpid() != 1)
1284         variable_set2(SYSTEM_STATE,             "update", 0);
1285     else
1286         variable_set2(SYSTEM_STATE,             "init", 0);
1287     variable_set2(VAR_NEWFS_ARGS,               "-b 16384 -f 2048", 0);
1288     variable_set2(VAR_CONSTERM,                 "NO", 0);
1289 #if (defined(__i386__) && !defined(PC98)) || defined(__amd64__)
1290     NCpus = acpi_detect();
1291     if (NCpus == -1)
1292         NCpus = biosmptable_detect();
1293 #endif
1294     if (NCpus <= 0)
1295         NCpus = 1;
1296     snprintf(ncpus, sizeof(ncpus), "%u", NCpus);
1297     variable_set2(VAR_NCPUS,                    ncpus, 0);
1298     return DITEM_SUCCESS;
1299 }
1300
1301 /* Load the environment up from various system configuration files */
1302 void
1303 installEnvironment(void)
1304 {
1305     configEnvironmentRC_conf();
1306     if (file_readable("/etc/resolv.conf"))
1307         configEnvironmentResolv("/etc/resolv.conf");
1308 }
1309
1310 /* Copy the boot floppy contents into /stand */
1311 Boolean
1312 copySelf(void)
1313 {
1314     int i;
1315
1316     if (file_readable("/boot.help"))
1317         vsystem("cp /boot.help /mnt");
1318     msgWeHaveOutput("Copying the boot floppy to /stand on root filesystem");
1319     i = vsystem("find -x /stand | cpio %s -pdum /mnt", cpioVerbosity());
1320     if (i) {
1321         msgConfirm("Copy returned error status of %d!", i);
1322         return FALSE;
1323     }
1324
1325     /* Copy the /etc files into their rightful place */
1326     if (vsystem("cd /mnt/stand; find etc | cpio %s -pdum /mnt", cpioVerbosity())) {
1327         msgConfirm("Couldn't copy up the /etc files!");
1328         return TRUE;
1329     }
1330     return TRUE;
1331 }
1332
1333 static void
1334 create_termcap(void)
1335 {
1336     FILE *fp;
1337
1338     const char *caps[] = {
1339         termcap_vt100, termcap_cons25, termcap_cons25_m, termcap_cons25r,
1340         termcap_cons25r_m, termcap_cons25l1, termcap_cons25l1_m,
1341         termcap_xterm, NULL,
1342     };
1343     const char **cp;
1344
1345     if (!file_readable(TERMCAP_FILE)) {
1346         Mkdir("/usr/share/misc");
1347         fp = fopen(TERMCAP_FILE, "w");
1348         if (!fp) {
1349             msgConfirm("Unable to initialize termcap file. Some screen-oriented\nutilities may not work.");
1350             return;
1351         }
1352         cp = caps;
1353         while (*cp)
1354             fprintf(fp, "%s\n", *(cp++));
1355         fclose(fp);
1356     }
1357 }