]> CyberLeo.Net >> Repos - FreeBSD/releng/9.2.git/blob - usr.sbin/sysinstall/install.c
- Copy stable/9 to releng/9.2 as part of the 9.2-RELEASE cycle.
[FreeBSD/releng/9.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     int need_eject;
361
362     if (!RunningAsInit)
363         return DITEM_SUCCESS;
364
365     variable_set2(SYSTEM_STATE, "fixit", 0);
366     need_eject = 0;
367     CDROMInitQuiet = 1;
368     while (1) {
369         if (need_eject)
370             msgConfirm(
371         "Please insert a FreeBSD live filesystem CD/DVD and press return");
372         if (DITEM_STATUS(mediaSetCDROM(NULL)) != DITEM_SUCCESS
373             || !DEVICE_INIT(mediaDevice)) {
374             /* If we can't initialize it, it's probably not a FreeBSD CDROM so punt on it */
375             mediaClose();
376             if (need_eject && msgYesNo("Unable to mount the disc. Do you want to try again?") != 0)
377                 return DITEM_FAILURE;
378         } else if (!file_readable("/dist/rescue/ldconfig")) {
379                 mediaClose();
380                 if (need_eject &&
381                     msgYesNo("Unable to find a FreeBSD live filesystem. Do you want to try again?") != 0)
382                     return DITEM_FAILURE;
383         } else
384             break;
385         CDROMInitQuiet = 0;
386         need_eject = 1;
387     }
388     CDROMInitQuiet = 0;
389
390     if (DITEM_STATUS(fixit_livefs_common(self)) == DITEM_FAILURE)
391         return (DITEM_FAILURE);
392
393     mediaClose();
394     if (need_eject)
395         msgConfirm("Please remove the FreeBSD fixit CDROM/DVD now.");
396     return DITEM_SUCCESS;
397 }
398
399 int
400 installFixitFloppy(dialogMenuItem *self)
401 {
402     struct ufs_args args;
403     extern char *distWanted;
404
405     if (!RunningAsInit)
406         return DITEM_SUCCESS;
407
408     /* Try to open the floppy drive */
409     if (DITEM_STATUS(mediaSetFloppy(NULL)) == DITEM_FAILURE || !mediaDevice) {
410         msgConfirm("Unable to set media device to floppy.");
411         mediaClose();
412         return DITEM_FAILURE;
413     }
414
415     memset(&args, 0, sizeof(args));
416     args.fspec = mediaDevice->devname;
417     mediaDevice->private = "/mnt2";
418     distWanted = NULL;
419     Mkdir("/mnt2");
420
421     variable_set2(SYSTEM_STATE, "fixit", 0);
422
423     while (1) {
424         if (!DEVICE_INIT(mediaDevice)) {
425             if (msgYesNo("The attempt to mount the fixit floppy failed, bad floppy\n"
426                          "or unclean filesystem.  Do you want to try again?"))
427                 return DITEM_FAILURE;
428         }
429         else
430             break;
431     }
432     if (!directory_exists("/tmp"))
433         (void)symlink("/mnt2/tmp", "/tmp");
434     fixit_common();
435     mediaClose();
436     msgConfirm("Please remove the fixit floppy now.");
437     return DITEM_SUCCESS;
438 }
439
440 /*
441  * The common code for both fixit variants.
442  */
443 static void
444 fixit_common(void)
445 {
446     pid_t child;
447     int waitstatus;
448
449     if (!directory_exists("/var/tmp/vi.recover")) {
450         if (DITEM_STATUS(Mkdir("/var/tmp/vi.recover")) != DITEM_SUCCESS) {
451             msgConfirm("Warning:  Was unable to create a /var/tmp/vi.recover directory.\n"
452                        "vi will kvetch and moan about it as a result but should still\n"
453                        "be essentially usable.");
454         }
455     }
456     if (!directory_exists("/bin"))
457         (void)Mkdir("/bin");
458     (void)symlink("/stand/sh", "/bin/sh");
459     /* Link the /etc/ files */
460     if (DITEM_STATUS(Mkdir("/etc")) != DITEM_SUCCESS)
461         msgConfirm("Unable to create an /etc directory!  Things are weird on this floppy..");
462     else if ((symlink("/mnt2/etc/spwd.db", "/etc/spwd.db") == -1 && errno != EEXIST) ||
463              (symlink("/mnt2/etc/protocols", "/etc/protocols") == -1 && errno != EEXIST) ||
464              (symlink("/mnt2/etc/group", "/etc/group") == -1 && errno != EEXIST) ||
465              (symlink("/mnt2/etc/services", "/etc/services") == -1 && errno != EEXIST))
466         msgConfirm("Couldn't symlink the /etc/ files!  I'm not sure I like this..");
467     if (!file_readable(TERMCAP_FILE))
468         create_termcap();
469     if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) 
470         systemSuspendDialog();  /* must be before the fork() */
471     if (!(child = fork())) {
472         int i, fd;
473         struct termios foo;
474         extern int login_tty(int);
475
476         ioctl(0, TIOCNOTTY, NULL);
477         for (i = getdtablesize(); i >= 0; --i)
478             close(i);
479
480         if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) 
481             fd = open("/dev/console", O_RDWR);
482         else
483             fd = open("/dev/ttyv3", O_RDWR);
484         ioctl(0, TIOCSCTTY, &fd);
485         dup2(0, 1);
486         dup2(0, 2);
487         DebugFD = 2;
488         if (login_tty(fd) == -1)
489             msgDebug("fixit: I can't set the controlling terminal.\n");
490
491         signal(SIGTTOU, SIG_IGN);
492         if (tcgetattr(0, &foo) != -1) {
493             foo.c_cc[VERASE] = '\010';
494             if (tcsetattr(0, TCSANOW, &foo) == -1)
495                 msgDebug("fixit shell: Unable to set erase character.\n");
496         }
497         else
498             msgDebug("fixit shell: Unable to get terminal attributes!\n");
499         setenv("PATH", "/bin:/sbin:/usr/bin:/usr/sbin:/stand:"
500                "/mnt2/stand:/mnt2/bin:/mnt2/sbin:/mnt2/usr/bin:/mnt2/usr/sbin", 1);
501         if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) {
502             printf("Waiting for fixit shell to exit.\n"
503                 "When you are done, type ``exit'' to exit\n"
504                 "the fixit shell and be returned here.\n\n");
505             fflush(stdout);
506         } else {
507             ioctl(fd, VT_ACTIVATE, 0);
508         }
509
510         /* use the .profile from the fixit medium */
511         setenv("HOME", "/mnt2", 1);
512         chdir("/mnt2");
513         execlp("sh", "-sh", (char *)0);
514         msgDebug("fixit shell: Failed to execute shell!\n");
515         _exit(1);;
516     }
517     else {
518         if (strcmp(variable_get(VAR_FIXIT_TTY), "standard") == 0) {
519             dialog_clear_norefresh();
520             msgNotify("Waiting for fixit shell to exit.  Go to VTY4 now by\n"
521                 "typing ALT-F4.  When you are done, type ``exit'' to exit\n"
522                 "the fixit shell and be returned here.\n");
523         }
524         (void)waitpid(child, &waitstatus, 0);
525         if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0)
526             systemResumeDialog();
527         else if (OnVTY) {
528             ioctl(0, VT_ACTIVATE, 0);
529             msgInfo(NULL);
530         }
531     }
532     dialog_clear();
533 }
534
535 /*
536  * Some path/lib setup is required for the livefs fixit image. Since there's
537  * more than one media type for livefs now, this has been broken off into it's
538  * own function.
539  */
540 int
541 fixit_livefs_common(dialogMenuItem *self)
542 {
543         struct stat sb;
544
545         /*
546          * USB and CDROM media get mounted to /dist, but fixit code looks in
547          * /mnt2.
548          */
549         unlink("/mnt2");
550         rmdir("/mnt2");
551
552         if (symlink("/dist", "/mnt2")) {
553                 msgConfirm("Unable to symlink /mnt2 to the disc mount point.");
554                 return (DITEM_FAILURE);
555         }
556
557         /*
558          * If /tmp points to /mnt2/tmp from a previous fixit floppy session,
559          * recreate it.
560          */
561         if (lstat("/tmp", &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFLNK)
562                 unlink("/tmp");
563         Mkdir("/tmp");
564
565         /* Generate a new ld.so.hints */
566         if (!file_readable("/var/run/ld.so.hints")) {
567                 Mkdir("/var/run");
568                 if (vsystem("/mnt2/rescue/ldconfig -s /mnt2/lib "
569                     "/mnt2/usr/lib")) {
570                         msgConfirm("Warning: ldconfig could not create the "
571                             "ld.so hints file.\nDynamic executables from the "
572                             "disc likely won't work.");
573                 }
574         }
575
576         /* Create required libexec symlinks. */
577         Mkdir("/libexec");
578         if (!file_readable("/libexec/ld.so") &&
579             file_readable("/mnt2/libexec/ld.so")) {
580                 if (symlink("/mnt2/libexec/ld.so", "/libexec/ld.so"))
581                         msgDebug("Couldn't link to ld.so\n");
582         }
583
584         if (!file_readable("/libexec/ld-elf.so.1")) {
585                 if (symlink("/mnt2/libexec/ld-elf.so.1",
586                     "/libexec/ld-elf.so.1")) {
587                         msgConfirm("Warning: could not create the symlink for "
588                             "ld-elf.so.1\nDynamic executables from the disc "
589                             "likely won't work.");
590                 }
591         }
592
593         /* $PATH doesn't include /mnt2 by default. Create convenient symlink. */
594         if (!file_readable("/usr/bin/vi"))
595                 symlink("/mnt2/usr/bin/vi", "/usr/bin/vi");
596
597         /* Shared code used by all fixit types. */
598         fixit_common();
599
600         return (DITEM_SUCCESS);
601 }
602
603 int
604 installExpress(dialogMenuItem *self)
605 {
606     int i;
607
608     dialog_clear_norefresh();
609     variable_set2(SYSTEM_STATE, "express", 0);
610 #ifdef WITH_SLICES
611     if (DITEM_STATUS((i = diskPartitionEditor(self))) == DITEM_FAILURE)
612         return i;
613 #endif
614     
615     if (DITEM_STATUS((i = diskLabelEditor(self))) == DITEM_FAILURE)
616         return i;
617
618     if (DITEM_STATUS((i = installCommit(self))) == DITEM_SUCCESS) {
619         i |= DITEM_LEAVE_MENU;
620
621         /* Give user the option of one last configuration spree */
622         installConfigure();
623     }
624     return i;
625 }
626
627 /* Standard mode installation */
628 int
629 installStandard(dialogMenuItem *self)
630 {
631     int i;
632 #ifdef WITH_SLICES
633     int tries = 0;
634     Device **devs;
635 #endif
636
637     variable_set2(SYSTEM_STATE, "standard", 0);
638     dialog_clear_norefresh();
639 #ifdef WITH_SLICES
640     msgConfirm("In the next menu, you will need to set up an MBR partitioning\n"
641                "scheme for your hard disk.  If you simply wish to devote all disk space\n"
642                "to FreeBSD (overwriting anything else that might be on the disk selected)\n"
643                "then use the (A)ll command to create a single partition followed\n"
644                "by a (Q)uit.  If you wish to allocate only free space to FreeBSD, move to a\n"
645                "partition marked \"unused\" and use the (C)reate command.");
646
647 nodisks:
648     if (DITEM_STATUS(diskPartitionEditor(self)) == DITEM_FAILURE)
649         return DITEM_FAILURE;
650
651     if (diskGetSelectCount(&devs) <= 0 && tries < 3) {
652         msgConfirm("You need to select some disks to operate on!  Be sure to use SPACE\n"
653                    "instead of RETURN in the disk selection menu when selecting a disk.");
654         ++tries;
655         goto nodisks;
656     }
657
658     msgConfirm("Now you need to create BSD partitions inside of the MBR partition(s)\n"
659                "just created.  If you have a reasonable amount of disk space (1GB or more)\n"
660                "and don't have any special requirements, simply use the (A)uto command to\n"
661                "allocate space automatically.  If you have more specific needs or just don't\n"
662                "care for the layout chosen by (A)uto, press F1 for more information on\n"
663                "manual layout.");
664 #else
665     msgConfirm("First you need to create BSD partitions on the disk which you are\n"
666                "installing to.  If you have a reasonable amount of disk space (1GB or more)\n"
667                "and don't have any special requirements, simply use the (A)uto command to\n"
668                "allocate space automatically.  If you have more specific needs or just don't\n"
669                "care for the layout chosen by (A)uto, press F1 for more information on\n"
670                "manual layout.");
671 #endif
672
673     if (DITEM_STATUS(diskLabelEditor(self)) == DITEM_FAILURE)
674         return DITEM_FAILURE;
675
676     if (DITEM_STATUS((i = installCommit(self))) == DITEM_FAILURE) {
677         dialog_clear();
678         msgConfirm("Installation completed with some errors.  You may wish to\n"
679                    "scroll through the debugging messages on VTY1 with the\n"
680                    "scroll-lock feature.  You can also choose \"No\" at the next\n"
681                    "prompt and reboot and try the installation again.");
682         return i;
683
684     }
685     else {
686         dialog_clear();
687         msgConfirm("Congratulations!  You now have FreeBSD installed on your system.\n\n"
688                    "We will now move on to the final configuration questions.\n"
689                    "For any option you do not wish to configure, simply select\n"
690                    "No.\n\n"
691                    "If you wish to re-enter this utility after the system is up, you\n"
692                    "may do so by typing: /usr/sbin/sysinstall.");
693     }
694     if (mediaDevice->type != DEVICE_TYPE_FTP && mediaDevice->type != DEVICE_TYPE_NFS) {
695         if (!msgYesNo("Would you like to configure any Ethernet or PLIP network devices?")) {
696             Device *tmp = tcpDeviceSelect();
697
698             if (tmp && !((DevInfo *)tmp->private)->use_dhcp && !msgYesNo("Would you like to bring the %s interface up right now?", tmp->name))
699                 if (!DEVICE_INIT(tmp))
700                     msgConfirm("Initialization of %s device failed.", tmp->name);
701         }
702         dialog_clear_norefresh();
703     }
704
705     if (!msgNoYes("Do you want this machine to function as a network gateway?"))
706         variable_set2("gateway_enable", "YES", 1);
707
708     dialog_clear_norefresh();
709     if (!msgNoYes("Do you want to configure inetd and the network services that it provides?"))
710         configInetd(self);
711
712     dialog_clear_norefresh();
713     if (!msgNoYes("Would you like to enable SSH login?"))
714         variable_set2("sshd_enable", "YES", 1);
715
716     dialog_clear_norefresh();
717     if (!msgNoYes("Do you want to have anonymous FTP access to this machine?"))
718         configAnonFTP(self);
719
720     dialog_clear_norefresh();
721     if (!msgNoYes("Do you want to configure this machine as an NFS server?"))
722         configNFSServer(self);
723
724     dialog_clear_norefresh();
725     if (!msgNoYes("Do you want to configure this machine as an NFS client?"))
726         variable_set2("nfs_client_enable", "YES", 1);
727
728 #ifdef WITH_SYSCONS
729     dialog_clear_norefresh();
730     if (!msgNoYes("Would you like to customize your system console settings?"))
731         dmenuOpenSimple(&MenuSyscons, FALSE);
732 #endif
733
734     dialog_clear_norefresh();
735     if (!msgYesNo("Would you like to set this machine's time zone now?"))
736         systemExecute("tzsetup");
737
738 #ifdef WITH_MICE
739     dialog_clear_norefresh();
740     if (!msgNoYes("Does this system have a PS/2, serial, or bus mouse?"))
741         dmenuOpenSimple(&MenuMouse, FALSE);
742 #endif
743
744 #ifdef __i386__
745     if (checkLoaderACPI() != 0) {
746         dialog_clear_norefresh();
747         if (!msgNoYes("ACPI was disabled during boot.\n"
748                       "Would you like to disable it permanently?"))
749                 (void)configLoaderACPI(1 /*disable*/);
750     }
751 #endif
752
753     /* Now would be a good time to checkpoint the configuration data */
754     configRC_conf();
755     sync();
756
757     dialog_clear_norefresh();
758     if (!msgYesNo("The FreeBSD package collection is a collection of thousands of ready-to-run\n"
759                   "applications, from text editors to games to Web servers and more.  Would you\n"
760                   "like to browse the collection now?")) {
761         (void)configPackages(self);
762     }
763
764     if (!msgYesNo("Would you like to add any initial user accounts to the system?\n"
765                   "Adding at least one account for yourself at this stage is suggested\n"
766                   "since working as the \"root\" user is dangerous (it is easy to do\n"
767                   "things which adversely affect the entire system)."))
768         (void)configUsers(self);
769
770     msgConfirm("Now you must set the system manager's password.\n"
771                "This is the password you'll use to log in as \"root\".");
772     if (!systemExecute("passwd root"))
773         variable_set2("root_password", "YES", 0);
774
775     /* XXX Put whatever other nice configuration questions you'd like to ask the user here XXX */
776
777     /* Give user the option of one last configuration spree */
778     dialog_clear_norefresh();
779     installConfigure();
780     return DITEM_LEAVE_MENU;
781 }
782
783 /* The version of commit we call from the Install Custom menu */
784 int
785 installCustomCommit(dialogMenuItem *self)
786 {
787     int i;
788
789     i = installCommit(self);
790     if (DITEM_STATUS(i) == DITEM_SUCCESS) {
791         /* Give user the option of one last configuration spree */
792         installConfigure();
793         return i;
794     }
795     else
796         msgConfirm("The commit operation completed with errors.  Not\n"
797                    "updating /etc files.");
798     return i;
799 }
800
801 /*
802  * What happens when we finally decide to going ahead with the installation.
803  *
804  * This is broken into multiple stages so that the user can do a full
805  * installation but come back here again to load more distributions,
806  * perhaps from a different media type.  This would allow, for
807  * example, the user to load the majority of the system from CDROM and
808  * then use ftp to load a different dist.
809  */
810 int
811 installCommit(dialogMenuItem *self)
812 {
813     int i;
814     char *str;
815
816     dialog_clear_norefresh();
817     if (!Dists)
818         distConfig(NULL);
819
820     if (!Dists) {
821         (void)dmenuOpenSimple(&MenuDistributions, FALSE);
822         /* select reasonable defaults if necessary */
823         if (!Dists)
824             Dists = _DIST_USER;
825         if (!KernelDists)
826             KernelDists = selectKernel();
827     }
828
829     if (!mediaVerify())
830         return DITEM_FAILURE;
831
832     str = variable_get(SYSTEM_STATE);
833     if (isDebug())
834         msgDebug("installCommit: System state is `%s'\n", str);
835
836     /* Installation stuff we wouldn't do to a running system */
837     if (RunningAsInit && DITEM_STATUS((i = installInitial())) == DITEM_FAILURE)
838         return i;
839
840 try_media:
841     if (!DEVICE_INIT(mediaDevice)) {
842         if (!msgYesNo("Unable to initialize selected media. Would you like to\n"
843                       "adjust your media configuration and try again?")) {
844             mediaDevice = NULL;
845             if (!mediaVerify())
846                 return DITEM_FAILURE;
847             else
848                 goto try_media;
849         }
850         else
851             return DITEM_FAILURE;
852     }
853
854     /* Now go get it all */
855     i = distExtractAll(self);
856
857     if (i == FALSE)
858             return DITEM_FAILURE;
859
860     /* When running as init, *now* it's safe to grab the rc.foo vars */
861     installEnvironment();
862
863     variable_set2(SYSTEM_STATE, DITEM_STATUS(i) == DITEM_FAILURE ? "error-install" : "full-install", 0);
864
865     return i;
866 }
867
868 static void
869 installConfigure(void)
870 {
871     /* Final menu of last resort */
872     if (!msgNoYes("Visit the general configuration menu for a chance to set\n"
873                   "any last options?"))
874         dmenuOpenSimple(&MenuConfigure, FALSE);
875     else
876         dmenuExit(NULL);
877
878     configRC_conf();
879     sync();
880 }
881
882 int
883 installFixupBase(dialogMenuItem *self)
884 {
885         FILE *orig, *new;
886         char buf[1024];
887         char *pos;
888 #if defined(__i386__) || defined(__amd64__)
889     FILE *fp;
890 #endif
891 #ifdef __ia64__
892     const char *efi_mntpt;
893 #endif
894
895     /* All of this is done only as init, just to be safe */
896     if (RunningAsInit) {
897 #if defined(__i386__) || defined(__amd64__)
898         if ((fp = fopen("/boot/loader.conf", "a")) != NULL) {
899             if (!OnVTY) {
900                 fprintf(fp, "# -- sysinstall generated deltas -- #\n");
901                 fprintf(fp, "console=\"comconsole\"\n");
902             }
903             fclose(fp);
904         }
905 #endif
906
907         /* Fixup /etc/ttys to start a getty on the serial port.
908           This way after a serial installation you can login via
909           the serial port */
910
911         if (!OnVTY){
912             if (((orig=fopen("/etc/ttys","r")) != NULL) &&
913                 ((new=fopen("/etc/ttys.tmp","w")) != NULL)) {
914                 while (fgets(buf,sizeof(buf),orig)){
915                     if (strstr(buf,"ttyu0")){
916                         if ((pos=strstr(buf,"off"))){
917                             *pos++='o';
918                             *pos++='n';
919                             *pos++=' ';
920                         }
921                     }
922                     fputs(buf,new);
923                 }
924                 fclose(orig);
925                 fclose(new);
926
927                 rename("/etc/ttys.tmp","/etc/ttys");
928                 unlink("/etc/ttys.tmp");
929             }
930         }
931
932         
933         /* BOGON #2: We leave /etc in a bad state */
934         chmod("/etc", 0755);
935         
936         /* BOGON #3: No /var/db/mountdtab complains */
937         Mkdir("/var/db");
938         creat("/var/db/mountdtab", 0644);
939         
940         /* BOGON #4: /compat created by default in root fs */
941         Mkdir("/usr/compat");
942         vsystem("ln -s usr/compat /compat");
943
944         /* BOGON #5: aliases database not built for bin */
945         vsystem("newaliases");
946
947         /* BOGON #6: Remove /stand (finally) */
948         vsystem("rm -rf /stand");
949
950         /* Now run all the mtree stuff to fix things up */
951         vsystem("mtree -deU -f /etc/mtree/BSD.root.dist -p /");
952         vsystem("mtree -deU -f /etc/mtree/BSD.var.dist -p /var");
953         vsystem("mtree -deU -f /etc/mtree/BSD.usr.dist -p /usr");
954
955 #ifdef __ia64__
956         /* Move /boot to the EFI partition and make /boot a link to it. */
957         efi_mntpt = (EfiChunk != NULL) ? ((PartInfo *)EfiChunk->private_data)->mountpoint : NULL;
958         if (efi_mntpt != NULL) {
959                 vsystem("if [ ! -L /boot ]; then mv /boot %s; fi", efi_mntpt);
960                 vsystem("if [ ! -e /boot ]; then ln -sf %s/boot /boot; fi",
961                     efi_mntpt + 1);     /* Skip leading '/' */
962                 /* Make sure the kernel knows which partition is the root file system. */
963                 vsystem("echo 'vfs.root.mountfrom=\"ufs:/dev/%s\"' >> /boot/loader.conf", RootChunk->name);
964         }
965 #endif
966
967         /* Do all the last ugly work-arounds here */
968     }
969     return DITEM_SUCCESS | DITEM_RESTORE;
970 }
971
972 int
973 installFixupKernel(dialogMenuItem *self, int dists)
974 {
975
976     /* All of this is done only as init, just to be safe */
977     if (RunningAsInit) {
978         /*
979          * Install something as /boot/kernel.
980          *
981          * NB: we assume any existing kernel has been saved
982          *     already and the /boot/kernel we remove is empty.
983          */
984         vsystem("rm -rf /boot/kernel");
985                 vsystem("mv /boot/" GENERIC_KERNEL_NAME " /boot/kernel");
986     }
987     return DITEM_SUCCESS | DITEM_RESTORE;
988 }
989
990 #define QUEUE_YES       1
991 #define QUEUE_NO        0
992 static int
993 performNewfs(PartInfo *pi, char *dname, int queue)
994 {
995         char buffer[LINE_MAX];
996
997         if (pi->do_newfs) {
998                 switch(pi->newfs_type) {
999                 case NEWFS_UFS:
1000                         snprintf(buffer, LINE_MAX, "%s %s %s %s %s",
1001                             NEWFS_UFS_CMD,
1002                             pi->newfs_data.newfs_ufs.softupdates ?  "-U" : "",
1003                             pi->newfs_data.newfs_ufs.ufs1 ? "-O1" : "-O2",
1004                             pi->newfs_data.newfs_ufs.user_options,
1005                             dname);
1006                         break;
1007
1008                 case NEWFS_MSDOS:
1009                         snprintf(buffer, LINE_MAX, "%s %s", NEWFS_MSDOS_CMD,
1010                             dname);
1011                         break;
1012
1013                 case NEWFS_CUSTOM:
1014                         snprintf(buffer, LINE_MAX, "%s %s",
1015                             pi->newfs_data.newfs_custom.command, dname);
1016                         break;
1017                 }
1018
1019                 if (queue == QUEUE_YES) {
1020                         command_shell_add(pi->mountpoint, "%s", buffer);
1021                         return (0);
1022                 } else
1023                         return (vsystem("%s", buffer));
1024         }
1025         return (0);
1026 }
1027
1028 /* Go newfs and/or mount all the filesystems we've been asked to */
1029 int
1030 installFilesystems(dialogMenuItem *self)
1031 {
1032     int i;
1033     Disk *disk;
1034     Chunk *c1, *c2;
1035     Device **devs;
1036     PartInfo *root;
1037     char dname[80];
1038     Boolean upgrade = FALSE;
1039
1040     /* If we've already done this, bail out */
1041     if (!variable_cmp(DISK_LABELLED, "written"))
1042         return DITEM_SUCCESS;
1043
1044     upgrade = !variable_cmp(SYSTEM_STATE, "upgrade");
1045     if (!checkLabels(TRUE))
1046         return DITEM_FAILURE;
1047
1048     root = (RootChunk != NULL) ? (PartInfo *)RootChunk->private_data : NULL;
1049
1050     command_clear();
1051     if (SwapChunk && RunningAsInit) {
1052         /* As the very first thing, try to get ourselves some swap space */
1053         sprintf(dname, "/dev/%s", SwapChunk->name);
1054         if (!Fake && !file_readable(dname)) {
1055             msgConfirm("Unable to find device node for %s in /dev!\n"
1056                        "The creation of filesystems will be aborted.", dname);
1057             return DITEM_FAILURE;
1058         }
1059
1060         if (!Fake) {
1061             if (!swapon(dname)) {
1062                 dialog_clear_norefresh();
1063                 msgNotify("Added %s as initial swap device", dname);
1064             }
1065             else {
1066                 msgConfirm("WARNING!  Unable to swap to %s: %s\n"
1067                            "This may cause the installation to fail at some point\n"
1068                            "if you don't have a lot of memory.", dname, strerror(errno));
1069             }
1070         }
1071     }
1072
1073     if (RootChunk && RunningAsInit) {
1074         /* Next, create and/or mount the root device */
1075         sprintf(dname, "/dev/%s", RootChunk->name);
1076         if (!Fake && !file_readable(dname)) {
1077             msgConfirm("Unable to make device node for %s in /dev!\n"
1078                        "The creation of filesystems will be aborted.", dname);
1079             return DITEM_FAILURE | DITEM_RESTORE;
1080         }
1081         if (strcmp(root->mountpoint, "/"))
1082             msgConfirm("Warning: %s is marked as a root partition but is mounted on %s", RootChunk->name, root->mountpoint);
1083
1084         if (root->do_newfs && (!upgrade ||
1085             !msgNoYes("You are upgrading - are you SURE you want to newfs "
1086             "the root partition?"))) {
1087             int i;
1088
1089             dialog_clear_norefresh();
1090             msgNotify("Making a new root filesystem on %s", dname);
1091             i = performNewfs(root, dname, QUEUE_NO);
1092             if (i) {
1093                 msgConfirm("Unable to make new root filesystem on %s!\n"
1094                            "Command returned status %d", dname, i);
1095                 return DITEM_FAILURE | DITEM_RESTORE;
1096             }
1097         }
1098         else {
1099             if (!upgrade) {
1100                 msgConfirm("Warning:  Using existing root partition.");
1101             }
1102             dialog_clear_norefresh();
1103             msgNotify("Checking integrity of existing %s filesystem.", dname);
1104             i = vsystem("fsck_ffs -y %s", dname);
1105             if (i)
1106                 msgConfirm("Warning: fsck returned status of %d for %s.\n"
1107                            "This partition may be unsafe to use.", i, dname);
1108         }
1109
1110         /*
1111          * If soft updates was enabled in the editor but we didn't newfs,
1112          * use tunefs to update the soft updates flag on the file system.
1113          */
1114         if (!root->do_newfs && root->newfs_type == NEWFS_UFS &&
1115             root->newfs_data.newfs_ufs.softupdates) {
1116                 i = vsystem("tunefs -n enable %s", dname);
1117                 if (i)
1118                         msgConfirm("Warning: Unable to enable soft updates"
1119                             " for root file system on %s", dname);
1120         }
1121
1122         /* Switch to block device */
1123         sprintf(dname, "/dev/%s", RootChunk->name);
1124         if (Mount("/mnt", dname)) {
1125             msgConfirm("Unable to mount the root file system on %s!  Giving up.", dname);
1126             return DITEM_FAILURE | DITEM_RESTORE;
1127         }
1128
1129         /* Mount devfs for other partitions to mount */
1130         Mkdir("/mnt/dev");
1131         if (!Fake) {
1132             struct iovec iov[4];
1133
1134             iov[0].iov_base = "fstype";
1135             iov[0].iov_len = strlen(iov[0].iov_base) + 1;
1136             iov[1].iov_base = "devfs";
1137             iov[1].iov_len = strlen(iov[1].iov_base) + 1;
1138             iov[2].iov_base = "fspath";
1139             iov[2].iov_len = strlen(iov[2].iov_base) + 1;
1140             iov[3].iov_base = "/mnt/dev";
1141             iov[3].iov_len = strlen(iov[3].iov_base) + 1;
1142             i = nmount(iov, 4, 0);
1143
1144             if (i) {
1145                 dialog_clear_norefresh();
1146                 msgConfirm("Unable to mount DEVFS (error %d)", errno);
1147                 return DITEM_FAILURE | DITEM_RESTORE;
1148             }
1149         }
1150     }
1151
1152     /* Now buzz through the rest of the partitions and mount them too */
1153     devs = deviceFind(NULL, DEVICE_TYPE_DISK);
1154     for (i = 0; devs[i]; i++) {
1155         if (!devs[i]->enabled)
1156             continue;
1157
1158         disk = (Disk *)devs[i]->private;
1159         if (!disk->chunks) {
1160             msgConfirm("No chunk list found for %s!", disk->name);
1161             return DITEM_FAILURE | DITEM_RESTORE;
1162         }
1163         for (c1 = disk->chunks->part; c1; c1 = c1->next) {
1164 #ifdef __ia64__
1165         if (c1->type == part) {
1166                 c2 = c1;
1167                 {
1168 #elif defined(__powerpc__)
1169             if (c1->type == apple) {
1170                 for (c2 = c1->part; c2; c2 = c2->next) {
1171 #else
1172             if (c1->type == freebsd) {
1173                 for (c2 = c1->part; c2; c2 = c2->next) {
1174 #endif
1175                     if (c2->type == part && c2->subtype != FS_SWAP && c2->private_data) {
1176                         PartInfo *tmp = (PartInfo *)c2->private_data;
1177
1178                         /* Already did root */
1179                         if (c2 == RootChunk)
1180                             continue;
1181
1182                         sprintf(dname, "%s/dev/%s",
1183                             RunningAsInit ? "/mnt" : "", c2->name);
1184
1185                         if (tmp->do_newfs && (!upgrade ||
1186                             !msgNoYes("You are upgrading - are you SURE you"
1187                             " want to newfs /dev/%s?", c2->name)))
1188                                 performNewfs(tmp, dname, QUEUE_YES);
1189                         else
1190                             command_shell_add(tmp->mountpoint,
1191                                 "fsck_ffs -y %s/dev/%s", RunningAsInit ?
1192                                 "/mnt" : "", c2->name);
1193 #if 0
1194                         if (tmp->soft)
1195                             command_shell_add(tmp->mountpoint,
1196                             "tunefs -n enable %s/dev/%s", RunningAsInit ?
1197                             "/mnt" : "", c2->name);
1198 #endif
1199                         command_func_add(tmp->mountpoint, Mount, c2->name);
1200                     }
1201                     else if (c2->type == part && c2->subtype == FS_SWAP) {
1202                         char fname[80];
1203                         int i;
1204
1205                         if (c2 == SwapChunk)
1206                             continue;
1207                         sprintf(fname, "%s/dev/%s", RunningAsInit ? "/mnt" : "", c2->name);
1208                         i = (Fake || swapon(fname));
1209                         if (!i) {
1210                             dialog_clear_norefresh();
1211                             msgNotify("Added %s as an additional swap device", fname);
1212                         }
1213                         else {
1214                             msgConfirm("Unable to add %s as a swap device: %s", fname, strerror(errno));
1215                         }
1216                     }
1217                 }
1218             }
1219             else if (c1->type == fat && c1->private_data &&
1220                 (root->do_newfs || upgrade)) {
1221                 char name[FILENAME_MAX];
1222
1223                 sprintf(name, "%s/%s", RunningAsInit ? "/mnt" : "", ((PartInfo *)c1->private_data)->mountpoint);
1224                 Mkdir(name);
1225             }
1226 #if defined(__ia64__)
1227             else if (c1->type == efi && c1->private_data) {
1228                 PartInfo *pi = (PartInfo *)c1->private_data;
1229
1230                 sprintf(dname, "%s/dev/%s", RunningAsInit ? "/mnt" : "",
1231                     c1->name);
1232
1233                 if (pi->do_newfs && (!upgrade ||
1234                     !msgNoYes("You are upgrading - are you SURE you want to "
1235                     "newfs /dev/%s?", c1->name)))
1236                         performNewfs(pi, dname, QUEUE_YES);
1237
1238                 command_func_add(pi->mountpoint, Mount_msdosfs, c1->name);
1239             }
1240 #endif
1241         }
1242     }
1243
1244     command_sort();
1245     command_execute();
1246     dialog_clear_norefresh();
1247     return DITEM_SUCCESS | DITEM_RESTORE;
1248 }
1249
1250 /* Initialize various user-settable values to their defaults */
1251 int
1252 installVarDefaults(dialogMenuItem *self)
1253 {
1254     char *cp, ncpus[10];
1255
1256     /* Set default startup options */
1257     cp = getsysctlbyname("kern.osrelease");
1258     variable_set2(VAR_RELNAME,                  cp, 0);
1259     free(cp);
1260     variable_set2(VAR_CPIO_VERBOSITY,           "high", 0);
1261     variable_set2(VAR_INSTALL_ROOT,             "/", 0);
1262     variable_set2(VAR_INSTALL_CFG,              "install.cfg", 0);
1263     cp = getenv("EDITOR");
1264     if (!cp)
1265         cp = "/usr/bin/ee";
1266     variable_set2(VAR_EDITOR,                   cp, 0);
1267     variable_set2(VAR_FTP_USER,                 "ftp", 0);
1268     variable_set2(VAR_BROWSER_PACKAGE,          "links", 0);
1269     variable_set2(VAR_BROWSER_BINARY,           "/usr/local/bin/links", 0);
1270     variable_set2(VAR_FTP_STATE,                "passive", 0);
1271     variable_set2(VAR_NFS_SECURE,               "NO", -1);
1272     variable_set2(VAR_NFS_TCP,                  "NO", -1);
1273     variable_set2(VAR_NFS_V3,                   "YES", -1);
1274     if (OnVTY)
1275             variable_set2(VAR_FIXIT_TTY,                "standard", 0);
1276     else
1277             variable_set2(VAR_FIXIT_TTY,                "serial", 0);
1278     variable_set2(VAR_PKG_TMPDIR,               "/var/tmp", 0);
1279     variable_set2(VAR_MEDIA_TIMEOUT,            itoa(MEDIA_TIMEOUT), 0);
1280     if (!RunningAsInit)
1281         variable_set2(SYSTEM_STATE,             "update", 0);
1282     else
1283         variable_set2(SYSTEM_STATE,             "init", 0);
1284     variable_set2(VAR_NEWFS_ARGS,               "-b 16384 -f 2048", 0);
1285     variable_set2(VAR_CONSTERM,                 "NO", 0);
1286     if (NCpus <= 0)
1287         NCpus = 1;
1288     snprintf(ncpus, sizeof(ncpus), "%u", NCpus);
1289     variable_set2(VAR_NCPUS,                    ncpus, 0);
1290     return DITEM_SUCCESS;
1291 }
1292
1293 /* Load the environment up from various system configuration files */
1294 void
1295 installEnvironment(void)
1296 {
1297     configEnvironmentRC_conf();
1298     if (file_readable("/etc/resolv.conf"))
1299         configEnvironmentResolv("/etc/resolv.conf");
1300 }
1301
1302 /* Copy the boot floppy contents into /stand */
1303 Boolean
1304 copySelf(void)
1305 {
1306     int i;
1307
1308     if (file_readable("/boot.help"))
1309         vsystem("cp /boot.help /mnt");
1310     msgWeHaveOutput("Copying the boot floppy to /stand on root filesystem");
1311     i = vsystem("find -x /stand | cpio %s -pdum /mnt", cpioVerbosity());
1312     if (i) {
1313         msgConfirm("Copy returned error status of %d!", i);
1314         return FALSE;
1315     }
1316
1317     /* Copy the /etc files into their rightful place */
1318     if (vsystem("cd /mnt/stand; find etc | cpio %s -pdum /mnt", cpioVerbosity())) {
1319         msgConfirm("Couldn't copy up the /etc files!");
1320         return TRUE;
1321     }
1322     return TRUE;
1323 }
1324
1325 static void
1326 create_termcap(void)
1327 {
1328     FILE *fp;
1329
1330     const char *caps[] = {
1331         termcap_vt100, termcap_cons25, termcap_cons25_m, termcap_cons25r,
1332         termcap_cons25r_m, termcap_cons25l1, termcap_cons25l1_m,
1333         termcap_xterm, NULL,
1334     };
1335     const char **cp;
1336
1337     if (!file_readable(TERMCAP_FILE)) {
1338         Mkdir("/usr/share/misc");
1339         fp = fopen(TERMCAP_FILE, "w");
1340         if (!fp) {
1341             msgConfirm("Unable to initialize termcap file. Some screen-oriented\nutilities may not work.");
1342             return;
1343         }
1344         cp = caps;
1345         while (*cp)
1346             fprintf(fp, "%s\n", *(cp++));
1347         fclose(fp);
1348     }
1349 }