home *** CD-ROM | disk | FTP | other *** search
- /*
- * install2.c
- *
- * This is the second half of the install. It is exec'd from the first half
- * once the secondary media has been mounted. It does a bunch of argv
- * processing to figure out what the first half did. It's a bit of a hack, but
- * it gives us a nice install as far as the user can see.
- *
- * Erik Troan (ewt@redhat.com)
- *
- * Copyright 1998 Red Hat Software
- *
- * This software may be freely redistributed under the terms of the GNU
- * public license.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-
- /*
- * We assume the following:
- *
- * /usr/bin -> any binaries we might need
- *
- * it's up to the first stage installer to make sure this happens.
- *
- */
-
- #include <dirent.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <newt.h>
- #include <popt.h>
- #include <rpm/rpmlib.h>
- #include <stdlib.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #include <sys/stat.h>
- #include <sys/sysmacros.h>
- #include <sys/time.h>
- #include <sys/wait.h>
- #include <termios.h>
- #include <unistd.h>
-
- #include "commands.h"
- #include "config.h"
- #include "devices.h"
- #include "doit.h"
- #include "fs.h"
- #include "fsedit.h"
- #include "hd.h"
- #include "otherinsmod.h"
- #include "install.h"
- #include "intl.h"
- #include "hints.h"
- #include "kbd.h"
- #include "kernel.h"
- #include "kickstart.h"
- #include "lang.h"
- #include "libfdisk/libfdisk.h"
- #include "lilo.h"
- #include "log.h"
- #include "methods.h"
- #include "mkswap.h"
- #include "net.h"
- #include "pkgs.h"
- #include "printercfg.h"
- #include "run.h"
- #include "scsi.h"
- #include "upgrade.h"
- #include "windows.h"
-
- int testing = 0;
- int expert = 0;
- int kickstart = 0;
- static int exitOnSuspend;
-
- #define STEP_FIRST 0
-
- #define STEP_PATH 0
- #define STEP_CLASS 1
- #define STEP_SCSI 2
- #define STEP_FDISKMTAB 3
- #define STEP_SWAP 4
- #define STEP_FINDPKGS 5
- #define STEP_FORMAT 6
- #define STEP_PICKPKGS 7
- #define STEP_DOIT 8
- #define STEP_FINISHNET 9
- #define STEP_TIMECONFIG 10
- #define STEP_SERVICES 11
- #define STEP_PRINTER 12
- #define STEP_ROOTPW 13
- #define STEP_BOOTDISK 14
- #define STEP_LILO 15
-
- #define STEP_UPG_SCSI 1
- #define STEP_UPG_PKGS 2
- #define STEP_UPG_MTAB 3
- #define STEP_UPG_FFILES 4
- #define STEP_UPG_DOIT 5
- #define STEP_UPG_BOOTDISK 6
- #define STEP_UPG_LILO 7
-
- #define STEP_DONE 1000
-
- struct installState {
- int isUpgrade, lastChoice, direction, isLocal;
- char * pcmcia, * kernel, * keyboard;
- struct partitionTable table;
- struct fstab fstab;
- struct pkgSet ps;
- struct componentSet cs;
- struct installMethod * method;
- struct intfInfo intf, intfFinal;
- struct netInfo netc, netcFinal;
- struct driversLoaded * dl;
- struct installStep * steps;
- char * rootPath;
- struct hints hints;
- } ;
-
- typedef int (*installStepFn)(struct installState * state);
-
- /* hack */
- int rmmod_main(int argc, char ** argv);
-
- static int setupSCSI(struct installState * state);
- static int selectInstallClass(struct installState * state);
- static int partitionDisks(struct installState * state);
- static int setupSwap(struct installState * state);
- static int findInstallFiles(struct installState * state);
- static int formatPartitions(struct installState * state);
- static int choosePackages(struct installState * state);
- static int doInstallStep(struct installState * state);
- static int setRootPassword(struct installState * state);
- static int createBootdisk(struct installState * state);
- static int configureTimezone(struct installState * state);
- static int configureServices(struct installState * state);
- static int configurePrinter(struct installState * state);
- static int setupBootloader(struct installState * state);
- static int finishNetworking(struct installState * state);
- static int selectPath(struct installState * state);
- static int upgrChoosePackages(struct installState * state);
- static int upgrFindInstall(struct installState * state);
- static void setupSerialConsole(void);
-
- struct installStep {
- char * name;
- int prev, next;
- installStepFn fn;
- int skipOnCancel, completed;
- int skipOnLocal;
- };
-
- /* this table is translated at run time */
- static struct installStep installSteps[] = {
- { N_("Select installation path"), -1, STEP_CLASS,
- selectPath, 0, 0, 0 },
- { N_("Select installation class"), STEP_PATH, STEP_SCSI,
- selectInstallClass, 0, 0, 0 },
- { N_("Setup SCSI"), STEP_CLASS, STEP_FDISKMTAB,
- setupSCSI, 0, 0, 1 },
- { N_("Setup filesystems"), STEP_SCSI, STEP_SWAP,
- partitionDisks, 0, 0, 1 },
- { N_("Setup swap space"), STEP_FDISKMTAB, STEP_FINDPKGS,
- setupSwap, 0, 0, 1 },
- { N_("Find installation files"), STEP_SWAP, STEP_FORMAT,
- findInstallFiles, 1, 0, 0 },
- { N_("Choose partitions to format"),STEP_SWAP, STEP_PICKPKGS,
- formatPartitions, 0, 0, 1 },
- { N_("Choose packages to install"), STEP_FORMAT, STEP_DOIT,
- choosePackages, 0, 0, 0 },
- { N_("Install system"), STEP_PICKPKGS, STEP_FINISHNET,
- doInstallStep, 0, 0, 0 },
- { N_("Configure networking"), -1, STEP_TIMECONFIG,
- finishNetworking, 0, 0, 0 },
- { N_("Configure timezone"), STEP_FINISHNET, STEP_SERVICES,
- configureTimezone, 0, 0, 0 },
- { N_("Configure services"), STEP_TIMECONFIG,STEP_PRINTER,
- configureServices, 0, 0, 0 },
- { N_("Configure printer"), STEP_SERVICES, STEP_ROOTPW,
- configurePrinter, 0, 0, 0 },
- { N_("Set root password"), STEP_PRINTER, STEP_BOOTDISK,
- setRootPassword, 0, 0, 0 },
- { N_("Create bootdisk"), STEP_ROOTPW, STEP_LILO,
- createBootdisk, 0, 0, 1 },
- { N_("Install bootloader"), STEP_BOOTDISK, STEP_DONE,
- setupBootloader, 0, 0, 1 },
- };
-
- /* this table is translated at run time */
- struct installStep upgradeSteps[] = {
- { N_("Select installation path"), -1, STEP_UPG_SCSI,
- selectPath, 0, 0, 0 },
- { N_("Setup SCSI"), STEP_PATH, STEP_UPG_PKGS,
- setupSCSI, 0, 0, 0 },
- { N_("Find installation files"), STEP_PATH, STEP_UPG_MTAB,
- findInstallFiles, 1, 0, 0 },
- { N_("Find current installation"), STEP_UPG_PKGS, STEP_UPG_FFILES,
- upgrFindInstall, 0, 0, 0 },
- { N_("Choose packages to upgrade"), STEP_UPG_FFILES,STEP_UPG_DOIT,
- upgrChoosePackages, 0, 0, 0 },
- { N_("Upgrade system"), STEP_UPG_FFILES,STEP_UPG_BOOTDISK,
- doInstallStep, 0, 0, 0 },
- { N_("Create bootdisk"), -1, STEP_UPG_LILO,
- createBootdisk, 0, 0, 0 },
- { N_("Install bootloader"), STEP_UPG_BOOTDISK, STEP_DONE,
- setupBootloader, 0, 0, 0 },
- };
-
- /* partition layout for a server */
- static struct attemptedPartition serverPartitioning[] = {
- #if defined(__i386__)
- { "/boot", 16, LINUX_NATIVE_PARTITION, 0, -1 },
- #elif defined(__alpha__)
- { "/dos", 2, DOS_PRIMARY_lt32MEG_PARTITION, 0, 1 },
- #endif
- { "/", 256, LINUX_NATIVE_PARTITION, 0, -1 },
- { "/usr", 512, LINUX_NATIVE_PARTITION, 1, -1 },
- { "/var", 256, LINUX_NATIVE_PARTITION, 0, -1 },
- { "/home", 512, LINUX_NATIVE_PARTITION, 1, -1 },
- { "Swap-auto", 64, LINUX_SWAP_PARTITION, 0, -1 },
- { NULL, 0, 0, 0 }
- };
-
- void spawnShell(void) {
- pid_t pid;
- int fd;
-
- if (!testing) {
- fd = open("/dev/tty2", O_RDWR);
- if (fd < 0) {
- logMessage("cannot open /dev/tty2 -- no shell will be provided");
- return;
- } else if (access("/bin/sh", X_OK)) {
- logMessage("cannot open shell - /usr/bin/sh doesn't exist");
- return;
- }
-
- if (!(pid = fork())) {
- dup2(fd, 0);
- dup2(fd, 1);
- dup2(fd, 2);
-
- close(fd);
- setsid();
- if (ioctl(0, TIOCSCTTY, NULL)) {
- perror("could not set new controlling tty");
- }
-
- execl("/bin/sh", "-/bin/sh", NULL);
- logMessage("exec of /bin/sh failed: %s", strerror(errno));
- }
-
- close(fd);
- }
- }
-
- static int setupSCSI(struct installState * state) {
- struct driversLoaded * drivers;
-
- if (state->direction < 0 && scsiDeviceAvailable())
- return INST_CANCEL;
-
- /* If we have any scsi adapters configured from earlier, then
- don't bother asking again */
- drivers = state->dl;
- while (drivers && drivers->type != DRIVER_SCSI)
- drivers = drivers->next;
- if (drivers) return INST_OKAY;
-
- return setupSCSIInterfaces(0, &state->dl,
- state->hints.flags & HINT_AUTOSCSI, state->direction);
- }
-
- static int useNewFdisk(int * useNew) {
- int rc;
-
- rc = newtWinTernary(_("Disk Setup"), _("Disk Druid"), _("fdisk"),
- _("Back"),
- _("Disk Druid is a tool for partitioning and setting up mount "
- "points. It is designed to be easier to use than Linux's "
- "traditional disk partitioning sofware, fdisk, as well "
- "as more powerful. However, there are some cases where fdisk "
- "may be preferred.\n\n"
- "Which tool would you like to use?"));
-
- if (rc == 3)
- return INST_CANCEL;
-
- if (rc == 0 || rc == 1)
- *useNew = 1;
- else
- *useNew = 0;
-
- return 0;
- }
-
- #define PART_METHOD 0
- #define PART_DDRUID 1
- #define PART_FDISK 2
- #define PART_FSTAB 3
- #define PART_DONE 10
-
- static int partitionDisks(struct installState * state) {
- int rc = 0;
- char ** drives;
- static int useNew;
- int numDrives;
- int stage;
- int dir;
-
- if (state->isUpgrade)
- return findAllPartitions(NULL, &state->table);
-
- if (kickstart) {
- if ((rc = getDriveList(&drives, &numDrives))) return rc;
- return kickstartPartitioning(&state->table, &state->fstab, drives);
- }
-
- if (state->direction > 0)
- stage = PART_METHOD;
- else
- stage = PART_DDRUID;
-
- while (stage != 10) {
- switch (stage) {
- case PART_METHOD:
- if (state->hints.flags & HINT_FORCEDDRUID) {
- if (dir < 0) return INST_CANCEL;
- useNew = 1;
- } else {
- if ((rc = useNewFdisk(&useNew))) return rc;
- }
- stage = useNew ? PART_DDRUID : PART_FDISK;
- dir = 1;
- break;
-
- case PART_DDRUID:
- if ((rc = getDriveList(&drives, &numDrives))) return rc;
- rc = FSEditPartitions(&state->table, &state->fstab, drives,
- &state->intf, &state->netc, &state->dl,
- state->hints.partitioning.attempts,
- (useNew ? 0 : FSEDIT_READONLY) |
- state->hints.partitioning.flags);
- if (rc == INST_ERROR) return rc;
- stage = PART_DONE, dir = 1;
- if (rc && useNew)
- stage = PART_METHOD, dir = -1;
- else if (rc)
- stage = PART_FDISK;
- break;
-
- case PART_FDISK:
- if ((rc = partitionDrives()) == INST_ERROR) return rc;
- stage = PART_DDRUID, dir = 1;
- if (rc) stage = PART_METHOD, dir = -1;
- break;
- }
- }
-
- return 0;
- }
-
- static int findInstallFiles(struct installState * state) {
- int rc;
- char * trFile;
-
- if (!state->table.parts) {
- rc = findAllPartitions(NULL, &state->table);
- if (rc) return rc;
- }
-
- if (state->method->prepareRoot) {
- rc = state->method->prepareRoot(state->method, state->table,
- &state->netc, &state->intf,
- &state->dl);
- if (rc) return rc;
- }
-
- /* We can now load the third bit of the install. FIXME: This leaks
- memory if we keep redoing it. I suspect much of this code does
- though! */
- if (state->method->getFile(state->method, "install3.tr", &trFile)) {
- logMessage("getFile method failed for %s", "install3.tr");
- } else {
- loadLanguageStage(3, trFile);
- if (state->method->rmFiles) unlink(trFile);
- }
-
- /* XXX Hack as we did this after freezing the translations */
- if (!getenv("LANG"))
- winStatus(25, 3, "Scanning", _("Scanning packages..."));
-
- rc = state->method->getPackageSet(state->method, &state->ps);
- if (!rc)
- rc = state->method->getComponentSet(state->method, &state->ps,
- &state->cs);
-
- if (!getenv("LANG"))
- newtPopWindow();
-
- return rc;
- }
-
- static int formatPartitions(struct installState * state) {
- int i;
-
- if (state->hints.flags & HINT_AUTOFORMAT) {
- if (state->direction < 0) return INST_CANCEL;
-
- for (i = 0; i < state->fstab.numEntries; i++) {
- if (state->fstab.entries[i].type == PART_EXT2)
- state->fstab.entries[i].doFormat = 1;
- }
-
- return 0;
- }
-
- return queryFormatFilesystems(&state->fstab);
- }
-
- static int setupSwap(struct installState * state) {
- if ((state->hints.flags & HINT_AUTOSWAP) && state->direction < 0)
- return INST_CANCEL;
-
- return activeSwapSpace(&state->table, &state->fstab,
- state->hints.flags & HINT_AUTOSWAP);
- }
-
- static int choosePackages(struct installState * state) {
- if (state->hints.component && (state->direction < 0)) return INST_CANCEL;
- return psSelectPackages(&state->ps, &state->cs, state->hints.component,
- 0, 0);
- }
-
- static void emptyErrorCallback(void) {
- }
-
- static int doInstallStep(struct installState * state) {
- int rc;
- char * netSharedPath = NULL;
- FILE * f;
- int netSharedLength;
- int i;
- char * path;
- rpmErrorCallBackType old;
-
- if (!state->isUpgrade) {
- if (!(state->hints.flags & HINT_NOLOGMESSAGE) && !expert) {
- rc = newtWinChoice(_("Install log"), _("Ok"), _("Back"),
- _("A complete log of your installation will be in "
- "/tmp/install.log after rebooting your system. You "
- "may want to keep this file for later reference."));
- if (rc == 2) return INST_CANCEL;
- }
-
- rc = formatFilesystems(&state->fstab);
- if (rc) return rc;
-
- rc = mountFilesystems(&state->fstab);
- if (rc) return rc;
-
- if (state->method->prepareMedia) {
- rc = state->method->prepareMedia(state->method, &state->fstab);
- if (rc) {
- umountFilesystems(&state->fstab);
- return rc;
- }
- }
- } else {
- do {
- if (!(state->hints.flags & HINT_NOLOGMESSAGE) && !expert) {
- rc = newtWinChoice(_("Upgrade log"), _("Ok"), _("Back"),
- _("A complete log of your upgrade will be in "
- "/tmp/upgrade.log when the upgrade is finished. "
- "After rebooting, please read it to ensure "
- "configuration files are properly updated."));
- if (rc == 2) return INST_CANCEL;
- }
-
- winStatus(40, 3, _("Rebuilding"), _("Rebuilding RPM database..."));
- rc = 0;
- if (!testing) {
- old = rpmErrorSetCallback(emptyErrorCallback);
- rpmSetVerbosity(RPMMESS_QUIET);
- rc = rpmdbRebuild("/mnt");
- rpmErrorSetCallback(old);
- rpmSetVerbosity(RPMMESS_NORMAL);
- newtPopWindow();
- if (rc) {
- newtWinMessage(_("Error"), _("Ok"), _("Rebuild of RPM "
- "database failed. You may be out of disk space?"));
- continue;
- }
- }
- } while (rc);
- }
-
- /* FIXME: should this read the net shared path from /etc/rpmrc
- during upgrades??? Probably. */
- for (i = netSharedLength = 0; i < state->fstab.numEntries; i++)
- if (state->fstab.entries[i].type == PART_NFS)
- netSharedLength += 1 + strlen(state->fstab.entries[i].mntpoint);
-
- if (netSharedLength) {
- netSharedPath = alloca(netSharedLength);
- *netSharedPath = '\0';
- for (i = netSharedLength = 0; i < state->fstab.numEntries; i++) {
- if (state->fstab.entries[i].type == PART_NFS) {
- if (*netSharedPath) strcat(netSharedPath, ":");
- strcat(netSharedPath, state->fstab.entries[i].mntpoint);
- }
- }
-
- logMessage("netSharedPath is: %s\n", netSharedPath);
- }
-
- rc = doInstall(state->method, state->rootPath, &state->ps,
- netSharedPath, state->keyboard, state->isUpgrade);
-
- path = alloca(strlen(state->rootPath) + 200);
- sprintf(path, "%s/etc/rpmrc", state->rootPath);
- if (netSharedPath && access(path, X_OK)) {
- logMessage("creating /etc/rpmrc for netshared info (as none exists)");
- f = fopen(path, "w");
- if (!f) {
- newtWinMessage(_("Error"), _("Ok"),
- "error creating path: %s", path, strerror(errno));
- } else {
- fprintf(f, "netsharedpath: %s\n", netSharedPath);
- fclose(f);
- }
- }
-
- sync();
- sync();
-
- if (!rc) psFreeComponentSet(&state->cs);
-
- configPCMCIA(state->rootPath, state->pcmcia);
-
- return rc;
- }
-
-
- static char mksalt(int seed) {
- int num = seed % 64;
-
- if (num < 26)
- return 'a' + num;
- else if (num < 52)
- return 'A' + (num - 26);
- else if (num < 62)
- return '0' + (num - 52);
- else if (num == 63)
- return '.';
- else
- return '/';
- }
-
- static int setRootPassword(struct installState * state) {
- newtComponent form = NULL, text, pw1Entry, pw2Entry, okay, cancel, answer;
- char * pw1 = NULL, * pw2;
- int done = 0;
- char salt[3];
- char cmd[200];
- struct timeval time1, time2;
- char * pw;
- pid_t pid;
- int status, rc;
- static int beenSet = 0;
- char ** argv;
- int argc;
- poptContext optCon;
- int skipCrypt = 0;
- char * reflowedText;
- char * path, * newpath;
- int height, width;
- newtGrid grid, subgrid, buttons;
- struct poptOption ksOptions[] = {
- { "iscrypted", '\0', POPT_ARG_NONE, &skipCrypt, 0 },
- { 0, 0, 0, 0, 0 }
- };
-
- if (kickstart) {
- if (!ksGetCommand(KS_CMD_ROOTPW, NULL, &argc, &argv)) {
- optCon = poptGetContext(NULL, argc, argv, ksOptions, 0);
-
- if ((rc = poptGetNextOpt(optCon)) < -1) {
- newtWinMessage(_("rootpw command"), _("Ok"),
- _("bad argument to kickstart rootpw command %s: %s"),
- poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
- poptStrerror(rc));
- }
-
- if (!(pw1 = poptGetArg(optCon))) {
- newtWinMessage(_("rootpw command"), _("Ok"),
- _("Missing password"));
- skipCrypt = 0;
- }
-
- if (poptGetArg(optCon))
- newtWinMessage(_("rootpw command"), _("Ok"),
- _("Unexpected arguments"));
-
- poptFreeContext(optCon);
- }
- }
-
- if (!pw1) {
- gettimeofday(&time1, NULL);
-
- subgrid = newtCreateGrid(2, 2);
- newtGridSetField(subgrid, 0, 0, NEWT_GRID_COMPONENT,
- newtLabel(-1, -1, _("Password:")),
- 0, 0, 1, 0, NEWT_ANCHOR_LEFT, 0);
- newtGridSetField(subgrid, 0, 1, NEWT_GRID_COMPONENT,
- newtLabel(-1, -1, _("Password (again):")),
- 0, 0, 1, 0, NEWT_ANCHOR_LEFT, 0);
-
- pw1Entry = newtEntry(-1, -1, "", 24, &pw1, NEWT_ENTRY_HIDDEN);
- pw2Entry = newtEntry(-1, -1, "", 24, &pw2, NEWT_ENTRY_HIDDEN);
-
- newtGridSetField(subgrid, 1, 0, NEWT_GRID_COMPONENT, pw1Entry,
- 0, 0, 0, 0, 0, 0);
- newtGridSetField(subgrid, 1, 1, NEWT_GRID_COMPONENT, pw2Entry,
- 0, 0, 0, 0, 0, 0);
-
- reflowedText = newtReflowText(
- _("Pick a root password. You must type it twice to ensure you know "
- "what it is and didn't make a mistake in typing. Remember that the "
- "root password is a critical part of system security!"), 37,
- 5, 5, &width, &height);
-
- text = newtTextbox(1, 1, width, height, NEWT_TEXTBOX_WRAP);
- newtTextboxSetText(text, reflowedText);
- free(reflowedText);
- buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL);
-
- grid = newtGridBasicWindow(text, subgrid, buttons);
-
- form = newtForm(NULL, NULL, 0);
-
- newtGridAddComponentsToForm(grid, form, 1);
- newtGridWrappedWindow(grid, _("Root Password"));
- newtGridFree(grid, 1);
-
- do {
- newtFormSetCurrent(form, pw1Entry);
- answer = newtRunForm(form);
-
- if (answer == cancel) {
- newtPopWindow();
- newtFormDestroy(form);
- return INST_CANCEL;
- }
-
- if (testing) {
- done = 1;
- } else if (strcmp(pw1, pw2)) {
- newtWinMessage(_("Password Mismatch"), _("Ok"),
- _("The passwords you entered were different. Please "
- "try again."));
- newtEntrySet(pw1Entry, "", 0);
- newtEntrySet(pw2Entry, "", 0);
- } else if (!strlen(pw1) && beenSet) {
- newtFormDestroy(form);
- newtPopWindow();
- return INST_OKAY;
- } else if (strlen(pw1) < 6) {
- newtWinMessage(_("Password Mismatch"), _("Ok"),
- _("The root password must be at least 6 characters "
- "long."));
- newtEntrySet(pw1Entry, "", 0);
- newtEntrySet(pw2Entry, "", 0);
- } else
- done = 1;
- } while (!done);
-
- newtPopWindow();
-
- pw2 = alloca(strlen(pw1) + 1);
- strcpy(pw2, pw1);
- pw1 = pw2;
-
- newtFormDestroy(form);
- }
-
- if (testing) return 0;
-
- if (!skipCrypt) {
- gettimeofday(&time2, NULL);
-
- salt[0] = mksalt(time1.tv_usec);
- salt[1] = mksalt(time2.tv_usec);
- salt[2] = '\0';
-
- pw = crypt(pw1, salt);
- } else {
- pw = pw1;
- }
-
- sprintf(cmd, "/bin/sed 's&root:[^:]*:&root:%s:&' < /etc/passwd > "
- "/etc/passwd.new", pw);
-
- if (!(pid = fork())) {
- chroot(state->rootPath);
- chdir("/");
-
- exit(system(cmd));
- }
-
- waitpid(pid, &status, 0);
-
- path = alloca(strlen(state->rootPath) + 30);
- newpath = alloca(strlen(state->rootPath) + 30);
- sprintf(path, "%s/etc/passwd", state->rootPath);
- sprintf(newpath, "%s/etc/passwd.new", state->rootPath);
- unlink(path);
- rename(newpath, path);
-
- beenSet = 1;
-
- return 0;
- }
-
- static int configureTimezone(struct installState * state) {
- return timeConfig(state->rootPath);
- }
-
- static int configureServices(struct installState * state) {
- if (state->hints.flags & HINT_SKIPNTSYSV)
- return (state->direction < 0) ? INST_CANCEL : INST_OKAY;
- else
- return servicesConfig(state->rootPath);
- }
-
- static int setupBootloader(struct installState * state) {
- static int first = 1;
- #ifdef __alpha
- int rc;
- #else
- char * versionString;
- int rc;
- int append = 0;
- char * version, * release;
- int i;
- #endif
-
- if (!state->isUpgrade && first) {
- setupSerialConsole();
- }
-
- #ifdef __alpha__
- if (first) {
- first = 0;
- rc = kernelCopy(state->kernel);
- if (rc) return rc;
- }
-
- return INST_NOP;
- #else
- first = 0;
-
- if (state->isUpgrade && !access("/mnt/etc/conf.modules", X_OK)) {
- rc = readModuleConfPersist("/mnt/etc", state->dl);
- if (rc) return rc;
- append = 1;
- }
-
- for (i = 0; i < state->ps.numPackages; i++) {
- if (!strncmp(state->ps.packages[i]->name, "kernel", 6)) break;
- }
-
- if (i == state->ps.numPackages) {
- errorWindow("I couldn't find a kernel!");
- return INST_ERROR;
- }
-
- headerGetEntry(state->ps.packages[i]->h, RPMTAG_VERSION, NULL,
- (void *) &version, NULL);
- headerGetEntry(state->ps.packages[i]->h, RPMTAG_RELEASE, NULL,
- (void *) &release, NULL);
-
- versionString = alloca(strlen(version) + strlen(release) + 2);
- sprintf(versionString, "%s-%s", version, release);
-
- logMessage("installed kernel version %s", versionString);
-
- /* installLilo installs silo on the SPARC */
- return installLilo("/mnt/etc", state->table, state->fstab,
- versionString, state->hints.bootloader.flags,
- state->hints.bootloader.options);
- #endif
- }
-
- static int finishNetworking(struct installState * state) {
- int rc;
- char * path = alloca(strlen(state->rootPath) + 50);
-
- rc = checkNetConfig(&state->intf, &state->netc, &state->intfFinal,
- &state->netcFinal, &state->dl, state->direction);
-
- if (rc) return rc;
-
- sprintf(path, "%s/etc/sysconfig", state->rootPath);
- writeNetConfig(path, &state->netcFinal,
- &state->intfFinal, 0);
- strcat(path, "/network-scripts");
- writeNetInterfaceConfig(path, &state->intfFinal);
- sprintf(path, "%s/etc", state->rootPath);
- writeResolvConf(path, &state->netcFinal);
-
- /* this is a bit of a hack */
- writeHosts(path, &state->netcFinal,
- &state->intfFinal, !state->isUpgrade);
-
- return 0;
- }
-
- static int selectPath(struct installState * state) {
- int result;
-
- memset(state, 0, sizeof(state));
-
- if (kickstart) {
- if (!ksGetCommand(KS_CMD_UPGRADE, NULL, NULL, NULL)) {
- state->steps = upgradeSteps;
- state->isUpgrade = 1;
- } else {
- state->steps = installSteps;
- }
-
- return 0;
- }
-
- result = newtWinChoice(_("Installation Path"), _("Install"), _("Upgrade"),
- _("Would you like to install a new system or upgrade a system which "
- "already contains Red Hat Linux 2.0 or later?"));
-
- if (result == 2) {
- state->steps = upgradeSteps;
- state->isUpgrade = 1;
- } else
- state->steps = installSteps;
-
- return 0;
- }
-
- static int selectInstallClass(struct installState * state) {
- int rc, i;
- static int choice = 2;
- char * choices[] = {
- N_("Workstation"),
- N_("Server"),
- N_("Custom"),
- NULL };
- char * transChoices[sizeof(choices) / sizeof(*choices)];
-
- if (expert || kickstart) {
- return state->direction < 0 ? INST_CANCEL : INST_OKAY;
- }
-
- for (i = 0; choices[i]; i++)
- transChoices[i] = _(choices[i]);
- transChoices[i] = NULL;
-
- rc = newtWinMenu(_("Installation Class"),
- _("What type of machine are you installing? For "
- "maximum flexibility, choose \"Custom\"."), 30,
- 10, 0, 5, transChoices, &choice, _("Ok"), _("Back"),
- NULL);
- if (rc == 2) return INST_CANCEL;
-
- memset(&state->hints, 0, sizeof(state->hints));
- if (choice == 2) return 0;
-
- state->hints.bootloader.flags = LILO_ON_MBR | LILO_USE_LINEAR;
- state->hints.flags = HINT_SKIPNTSYSV | HINT_AUTOFORMAT |
- HINT_NOLOGMESSAGE |
- HINT_AUTOSWAP | HINT_SKIPBOOTLOADER | HINT_FORCEDDRUID;
- state->hints.component = choices[choice];
- if (choice == 1) {
- /* server */
- state->hints.flags |= HINT_SKIPPRINTER;
- state->hints.partitioning.flags |= FSEDIT_CLEARALL; state->hints.partitioning.attempts = serverPartitioning;
- } else {
- /* workstation */
- state->hints.flags |= HINT_AUTOSCSI;
- #ifdef __i386__
- state->hints.partitioning.flags |= FSEDIT_CLEARLINUX;
- #else
- state->hints.partitioning.flags |= FSEDIT_CLEARALL;
- #endif
- }
-
- return INST_OKAY;
- }
-
- static int upgrFindInstall(struct installState * state) {
- int rc;
-
- /* this also turns on swap for us */
- rc = readMountTable(state->table, &state->fstab);
- if (rc) return rc;
-
- if (!testing) {
- mountFilesystems(&state->fstab);
-
- if (state->method->prepareMedia) {
- rc = state->method->prepareMedia(state->method, &state->fstab);
- if (rc) {
- umountFilesystems(&state->fstab);
- return rc;
- }
- }
- }
-
- return 0;
- }
-
- static int upgrChoosePackages(struct installState * state) {
- int firstTime = 1;
- char * rpmconvertbin;
- int rc;
- char * path;
- char * argv[] = { NULL, NULL };
-
- if (testing)
- path = "/";
- else
- path = "/mnt";
-
- if (firstTime) {
- if (access("/mnt/var/lib/rpm/packages.rpm", R_OK)) {
- if (access("/mnt/var/lib/rpm/packages", R_OK)) {
- errorWindow("No RPM database exists!");
- return INST_ERROR;
- }
-
- if (state->method->getFile(state->method, "rpmconvert",
- &rpmconvertbin)) {
- return INST_ERROR;
- }
-
- symlink("/mnt/var", "/var");
- winStatus(35, 3, _("Upgrade"), _("Converting RPM database..."));
- chmod(rpmconvertbin, 0755);
- argv[0] = rpmconvertbin;
- rc = runProgram(RUN_LOG, rpmconvertbin, argv);
- if (state->method->rmFiles)
- unlink(rpmconvertbin);
-
- newtPopWindow();
- if (rc) return INST_ERROR;
- }
-
- winStatus(35, 3, "Upgrade", _("Finding packages to upgrade..."));
- rc = ugFindUpgradePackages(&state->ps, path);
- newtPopWindow();
- if (rc) return rc;
- firstTime = 0;
- psVerifyDependencies(&state->ps, 1);
- }
-
- return psSelectPackages(&state->ps, &state->cs, NULL, 0, 1);
- }
-
- #define DO_RETRY 1
- #define DO_NEXT 2
- #define DO_PREV 3
- #define DO_MENU 4
-
- static int errcanChoices(char * name) {
- int rc;
-
- rc = newtWinTernary(_("Error"), _("Previous"), _("Retry"), _("Menu"),
- _("An error occured during step \"%s\" of the install.\n\n"
- "You may retry that step, return to the previous step "
- "in the install, or see a menu of installation steps "
- "which will allow you to move around in the install "
- "more freely. It is not recommended to use the menu "
- "unless you are already familiar with Red Hat Linux. "
- "What would you like to do?"), name);
-
- if (rc == 1 || !rc)
- return DO_PREV;
- else if (rc == 2)
- return DO_RETRY;
-
- return DO_MENU;
- }
-
- static int stepMenu(struct installState * state, int currStep) {
- int firstStep = currStep;
- long i;
- int numChoices, whichStep = 0;
- char ** steps;
-
- while (state->steps[firstStep].prev != -1)
- firstStep = state->steps[firstStep].prev;
-
- i = firstStep, numChoices = 0;
- do {
- numChoices++;
- i = state->steps[i].next;
- } while (state->steps[i].prev != -1 && state->steps[i].next != STEP_DONE);
- numChoices++;
-
- steps = alloca(sizeof(char *) * (numChoices + 2));
- steps[0] = _(" Continue with install");
- for (i = firstStep; i < (firstStep + numChoices); i++) {
- steps[i - firstStep + 1] = alloca(50);
- if (state->steps[i].completed)
- strcpy(steps[i - firstStep + 1], "* ");
- else
- strcpy(steps[i - firstStep + 1], " ");
-
- strcat(steps[i - firstStep + 1], state->steps[i].name);
- }
- steps[numChoices + 1] = NULL;
-
- newtWinMenu(_("Installation Steps"), _("What step would you like to run? "
- "Steps with a * next to them have already been completed."),
- 48, 5, 5, 6, steps, &whichStep, _("Ok"), NULL);
-
- if (whichStep == 0)
- return -1;
- else
- return (whichStep - 1) + firstStep;
-
- return i;
- }
-
- static int getNextStep(struct installState * state, int lastStep, int lastrc) {
- int choice;
- int nextStep;
-
- if (state->lastChoice == DO_MENU) {
- choice = DO_MENU;
- } else if (lastrc == INST_ERROR) {
- choice = errcanChoices(state->steps[lastStep].name);
- kickstart = 0;
- } else if (lastrc == INST_CANCEL) {
- choice = DO_PREV;
- } else if (lastrc == INST_NOP) {
- choice = state->lastChoice;
- } else {
- choice = DO_NEXT;
- }
-
- switch (choice) {
- case DO_PREV:
- nextStep = state->steps[lastStep].prev;
- while (nextStep != -1 &&
- (state->steps[nextStep].skipOnCancel ||
- (state->steps[nextStep].skipOnLocal && state->isLocal))
- && state->steps[nextStep].prev != -1)
- nextStep = state->steps[nextStep].prev;
-
- if (nextStep == -1 || nextStep == lastStep) {
- newtWinMessage(_("Cancelled"), _("Ok"),
- _("I can't go to the previous step"
- " from here. You will have to try again."));
- nextStep = lastStep;
- }
- state->direction = -1;
- break;
-
- case DO_RETRY:
- nextStep = lastStep;
- state->direction = -1;
- break;
-
- case DO_MENU:
- nextStep = stepMenu(state, lastStep);
- if (nextStep == -1) {
- choice = DO_NEXT;
-
- if (lastrc)
- nextStep = lastStep;
- else
- nextStep = state->steps[lastStep].next;
- }
- state->direction = 1;
- break;
-
- case DO_NEXT: default:
- nextStep = state->steps[lastStep].next;
- while (nextStep != STEP_DONE &&
- state->isLocal && state->steps[nextStep].skipOnLocal)
- nextStep = state->steps[nextStep].next;
- state->direction = 1;
- break;
- }
-
- state->lastChoice = choice;
-
- return nextStep;
- }
-
- void doSuspend(void) {
- pid_t pid;
- int status;
-
- if (exitOnSuspend) {
- newtFinished();
- exit(1);
- }
-
- newtSuspend();
- if (!(pid = fork())) {
- printf(_("\n\nType <exit> to return to the install program.\n\n"));
- execl("/bin/sh", "-/bin/sh", NULL);
- perror("error execing /bin/sh");
- sleep(5);
- exit(1);
- }
- waitpid(pid, &status, 0);
- newtResume();
- }
-
- static void setupSerialConsole(void) {
- int first = 1;
- struct stat sb;
- char * argv[10] = { "/usr/sbin/setconsole", "--speed", NULL, NULL, NULL };
- struct termios tos;
- speed_t speed;
-
- if (!first) return;
- first = 0;
-
- if (fstat(0, &sb)) {
- logMessage("error stat'ing stdin: %s", strerror(errno));
- return;
- }
-
- if (!S_ISCHR(sb.st_mode)) {
- logMessage("stdin isn't a character device!!! ack!");
- return;
- }
-
- if (major(sb.st_rdev) != 4) {
- if (minor(sb.st_rdev) == 64)
- argv[3] = "ttya";
- else
- argv[3] = "ttyb";
-
- tcgetattr(0, &tos);
- speed = cfgetospeed(&tos);
- switch (speed) {
- case B38400: argv[2] = "38400"; break;
- case B19200: argv[2] = "19200"; break;
- default: argv[2] = "9600"; break;
- }
-
- if (access("/mnt/usr/sbin/setconsole", X_OK)) {
- logMessage("/mnt/usr/sbin/setconsole does not exist -- skipping");
- return;
- }
-
- logMessage("setting up %s as serial console, speed is %s", argv[3],
- argv[2]);
- runProgramRoot(RUN_LOG, "/mnt", "/usr/sbin/setconsole", argv);
- }
- }
-
- static int configurePrinter(struct installState * state) {
- char * path = alloca(strlen(state->rootPath) + 50);
-
- sprintf(path, "%s/usr/bin/lpr", state->rootPath);
-
- if (state->hints.flags & HINT_SKIPPRINTER)
- return state->direction < 0 ? INST_CANCEL : INST_OKAY;
- else if (testing) {
- return doConfigurePrinters("/", state->direction);
- } else if (!access(path, X_OK)) {
- return doConfigurePrinters(state->rootPath, state->direction);
- }
-
- return INST_NOP;
- }
-
- static int createBootdisk(struct installState * state) {
- int rc;
- int i;
- char * version, * release;
- char * versionString;
- int stage = 1;
- static int beenHere = 0;
-
- if (!state->isUpgrade && !beenHere) {
- writeFstab(&state->fstab);
- }
- writeModuleConf("/mnt/etc", state->dl, 1);
- beenHere = 1;
-
- if (state->hints.flags & HINT_SKIPBOOTDISK) return INST_NOP;
-
- #ifndef __i386__
- return INST_NOP;
- #else
- if (!testing && (access("/mnt/sbin/mkbootdisk", X_OK) ||
- access("/mnt/sbin/mkinitrd", X_OK))) return INST_NOP;
-
- while (stage < 4) {
- switch (stage) {
- case 1:
- rc = newtWinTernary(_("Bootdisk"), _("Yes"), _("No"), _("Back"),
- _("A custom bootdisk provides a way of booting into your "
- "Linux system without depending on the normal bootloader. "
- "This is useful if you don't want to install lilo on your "
- "system, another operating system removes lilo, or lilo "
- "doesn't work with your hardware configuration. A custom "
- "bootdisk can also be used with the Red Hat rescue image, "
- "making is much easier to recover from severe system "
- "failures.\n\n"
- "Would you like to create a bootdisk for your system?"));
-
- if (rc == 3) return INST_CANCEL;
- if (rc == 2) return INST_OKAY;
- stage = 2;
- break;
-
- case 2:
- rc = newtWinChoice(_("Bootdisk"), _("Ok"), _("Back"),
- _("Insert a blank floppy in the first drive "
- "/dev/fd0."));
- if (rc == 2)
- stage = 1;
- else
- stage = 3;
- break;
-
- case 3:
- for (i = 0; i < state->ps.numPackages; i++) {
- if (!strncmp(state->ps.packages[i]->name, "kernel", 6)) break;
- }
-
- if (i == state->ps.numPackages) {
- errorWindow("I couldn't find a kernel!");
- return INST_ERROR;
- }
-
- headerGetEntry(state->ps.packages[i]->h, RPMTAG_VERSION, NULL,
- (void *) &version, NULL);
- headerGetEntry(state->ps.packages[i]->h, RPMTAG_RELEASE, NULL,
- (void *) &release, NULL);
- versionString = alloca(strlen(version) + strlen(release) + 2);
- sprintf(versionString, "%s-%s", version, release);
-
- rc = makeBootdisk("/mnt", versionString);
- if (rc == INST_ERROR) return INST_ERROR;
- stage++;
- break;
- }
- }
-
- return INST_OKAY;
- #endif
- }
-
- int main(int argc, char ** argv) {
- char ** argptr;
- int step = STEP_FIRST;
- int rc = 0;
- struct installState state;
- int i;
- int isForce = 0;
- int len = strlen(argv[0]);
- char * spaces;
- DIR * dir;
- struct dirent * ent;
- char * kickstartFile = NULL;
- int localInstall = 0;
-
- spaces = strdup(" ");
-
- if (!strcmp(argv[0] + len - 6, "umount")) {
- return umountCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 5, "mount")) {
- return mountCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 5, "mkdir")) {
- return mkdirCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 5, "mknod")) {
- return mknodCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 3, "cat")) {
- return catCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 2, "ls")) {
- return lsCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 2, "ln")) {
- return lnCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 2, "rm")) {
- return rmCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 5, "chmod")) {
- return chmodCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 5, "lsmod")) {
- return lsmodCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 6, "mkswap")) {
- return mkswapCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 6, "swapon")) {
- return swaponCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 6, "uncpio")) {
- return uncpioCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 6, "insmod")) {
- return ourInsmodCommand(argc, argv);
- } else if (!strcmp(argv[0] + len - 5, "rmmod")) {
- return rmmod_main(argc, argv);
- }
-
- /* if this fails, it's okay -- it might help with free space though */
- unlink("/sbin/install");
-
- memset(&state, 0, sizeof(state));
- state.steps = installSteps; /* blind guess */
- state.rootPath = "/mnt";
-
- argptr = argv + 1;
- while (*argptr) {
- if (!strcmp(*argptr, "--method")) {
- argptr++;
- if (!*argptr) {
- fprintf(stderr, "--method requires argument\n");
- exit(1);
- }
- state.method = findInstallMethod(*argptr);
- if (!state.method) {
- fprintf(stderr, "unknown install method: %s\n", *argptr);
- exit(1);
- }
- } else if (!strcmp(*argptr, "--force")) {
- isForce = 1;
- } else if (!strcmp(*argptr, "--kickstart") ||
- !strcmp(*argptr, "--ks")) {
- argptr++;
- if (!*argptr)
- fprintf(stderr, "--kickstart requires argument\n");
- kickstartFile = *argptr;
- } else if (!strcmp(*argptr, "--expert")) {
- expert = 1;
- } else if (!strcmp(*argptr, "--test")) {
- testing = 1;
- } else if (!strcmp(*argptr, "--pcmcia")) {
- argptr++;
- if (!*argptr) {
- fprintf(stderr, "--pcmcia requires argument\n");
- exit(1);
- }
- state.pcmcia = *argptr;
- } else if (!strcmp(*argptr, "--kernel")) {
- argptr++;
- if (!*argptr) {
- fprintf(stderr, "--kernel requires argument\n");
- exit(1);
- }
- state.kernel = *argptr;
- } else if (!strcmp(*argptr, "--rootpath")) {
- argptr++;
- if (!*argptr) {
- fprintf(stderr, "--rootpath requires argument\n");
- exit(1);
- }
- state.rootPath = *argptr;
- localInstall = 1;
- } else {
- /* skipping unknown arguments allows for future expansion */
- fprintf(stderr, "unknown argument: %s\n", *argptr);
- }
- argptr++;
- }
-
- if (!state.method) {
- fprintf(stderr, "--method argument is required\n");
- exit(1);
- }
-
- if (!testing && !localInstall && !isForce && (getpid() > 50)) {
- fprintf(stderr, "you're running me on a live system! that's ");
- fprintf(stderr, "incredibly stupid.\n");
- exit(1);
- }
-
- fprintf(stderr, "in second stage install\n");
-
- /* translate some tables */
- for (i = 0; installSteps[i].next != STEP_DONE; i++)
- installSteps[i].name = _(installSteps[i].name);
- installSteps[i].name = _(installSteps[i].name);
-
- for (i = 0; upgradeSteps[i].next != STEP_DONE; i++)
- upgradeSteps[i].name = _(upgradeSteps[i].name);
- upgradeSteps[i].name = _(upgradeSteps[i].name);
-
- state.isLocal = localInstall;
- exitOnSuspend = localInstall || testing;
-
- newtSetSuspendCallback(doSuspend);
-
- openLog(testing || localInstall);
-
- logMessage("second stage install running (version " VERSION " built "
- __DATE__ " " __TIME__ ")");
-
- logDebugMessage(("extra log messages are enabled"));
-
- spawnShell();
-
- newtInit();
- newtCls();
-
- newtDrawRootText(0, 0, "Red Hat Linux (C) 1998 Red Hat Software");
- newtPushHelpLine(_(" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen "));
-
- setDefaultLanguage(2);
-
- readNetConfig("/tmp", &state.netc);
-
- dir = opendir("/tmp");
- if (!dir)
- logMessage("failed to open directory /tmp: %s", strerror(errno));
- else {
- errno = 0;
- while ((ent = readdir(dir))) {
- if (!strncmp("ifcfg-", ent->d_name, 6)) break;
- }
-
- if (!ent && errno) {
- logMessage("error reading directory entry: %s", strerror(errno));
- } else if (ent) {
- logMessage("found network config file %s", ent->d_name);
- readNetInterfaceConfig("/tmp", ent->d_name + 6, &state.intf);
- }
- }
- closedir(dir);
-
- logMessage("reading /usr/lib/rpmrc");
- rpmReadConfigFiles(NULL, NULL, NULL, 0);
- logMessage("\tdone");
-
- readModuleConf("/tmp", &state.dl);
-
- /* make sure we don't pick up any gunk from the outside world */
- putenv("PATH=/usr/bin:/bin:/sbin:/usr/sbin");
- putenv("LD_LIBRARY_PATH=");
-
- if (kickstartFile) {
- if (ksReadCommands(kickstartFile))
- kickstartFile = NULL;
- else {
- kickstart = 1;
- ksToHints(&state.hints);
- }
-
- #ifndef __sparc__
- setupKeyboard(&state.keyboard);
- #endif
- } else {
- #ifndef __sparc__
- readKbdConfig("/tmp", &state.keyboard);
- #endif
- }
-
- if (kickstart) {
- state.hints.flags = HINT_SKIPNTSYSV | HINT_AUTOFORMAT |
- HINT_SKIPPRINTER | HINT_SKIPBOOTDISK |
- HINT_AUTOSWAP | HINT_AUTOSCSI | HINT_NOLOGMESSAGE;
- }
-
- while (step != STEP_DONE) {
- i = strlen(state.steps[step].name);
- newtDrawRootText(0 - i, 0, state.steps[step].name);
- newtRefresh();
- rc = state.steps[step].fn(&state);
- if (!rc)
- state.steps[step].completed = 1;
-
- spaces[i] = '\0';
- newtDrawRootText(0 - i, 0, spaces);
- spaces[i] = ' ';
-
- step = getNextStep(&state, step, rc);
- }
-
- if (kickstart)
- ksRunPost();
-
- newtDrawRootText(72, 0, _("Complete"));
- newtWinMessage(_("Done"), _("Ok"),
- _("Congratulations, installation is complete.\n\n"
- "Remove the floppy from the drive and "
- "press return to reboot. For information on fixes which are "
- "available for this release of Red Hat Linux, consult the "
- "Errata available from http://www.redhat.com.\n\n"
- "Information on configuring your system is available in the post "
- "install chapter of the Official Red Hat Linux User's Guide."));
-
- newtFinished();
-
- return 0;
- }
-