home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 February
/
CHIP_2_98.iso
/
misc
/
src
/
install
/
earlymethods.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-11-05
|
16KB
|
607 lines
#include <ctype.h>
#include <errno.h>
#include <fcntl.h>
#include <newt.h>
#include <popt.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <unistd.h>
#include "dns.h"
#include "hd.h"
#include "fs.h"
#include "install.h"
#include "kickstart.h"
#include "log.h"
#include "methods.h"
#include "net.h"
#include "windows.h"
/* disable the smb install as smbfs seems hosed in 2.0.31 */
#define SMB_INSTALL 0
/* This was split into two pieces to keep the initial install program small */
static int nfsPrepare(struct installMethod * method, struct netConfig * netc,
struct netInterface * intf, struct driversLoaded ** dl);
static int cdromPrepare(struct installMethod * method, struct netConfig * netc,
struct netInterface * intf, struct driversLoaded ** dl);
static int nfsGetSetup(char ** hostptr, char ** dirptr);
int floppyRoot(struct installMethod * method, struct netConfig * netc,
struct netInterface * intf, struct driversLoaded ** dl);
#if SMB_INSTALL
static int smbGetSetup(char ** hostptr, char ** dirptr, char ** acctptr,
char ** pwptr);
#endif
static int totalMemory(void); /* in K */
#define CDROM_METHOD_NUM 0
#define NFS_METHOD_NUM 1
static struct installMethod methods[] = {
{ "Local CDROM", "cdrom", 0, cdromPrepare, NULL, NULL,
NULL, NULL, NULL },
{ "NFS image", "nfs", 0, nfsPrepare, NULL, NULL,
NULL, NULL, NULL },
{ "hard drive", "hd", 0, floppyRoot, NULL, NULL,
NULL, NULL, NULL },
{ "FTP", "ftp", 0, floppyRoot, NULL, NULL,
NULL, NULL, NULL },
#if SMB_INSTALL
{ "SMB image", "smb", 0, floppyRoot, NULL, NULL,
NULL, NULL, NULL },
#endif
#if 0
{ "SCSI Tape Install", "tape", 0, floppyRoot, NULL, NULL,
NULL, NULL, NULL },
#endif
} ;
static int numMethods = sizeof(methods) / sizeof(struct installMethod);
#define LOAD_BLOCK_COUNT 16
static int loadRamdisk(char * todev, char * fromdev, int blocks,
char * label) {
newtComponent form, scale;
char * topath, * frompath;
char buf[LOAD_BLOCK_COUNT * 1024];
int rc = 0;
int i;
int to, from;
if (blocks % LOAD_BLOCK_COUNT) {
logMessage("internal error: blocks in loadRamdisk() must be "
"divisible by %d!!", LOAD_BLOCK_COUNT);
return 1;
}
topath = alloca(strlen(todev) + 8);
sprintf(topath, "/tmp/%s", todev);
frompath = alloca(strlen(fromdev) + 8);
sprintf(frompath, "/tmp/%s", fromdev);
if (devMakeInode(todev, topath)) return 1;
if (devMakeInode(fromdev, frompath)) {
unlink(topath);
return 1;
}
to = open(topath, O_WRONLY);
if (to < 0) {
logMessage("failed to open %s: %s", topath, strerror(errno));
unlink(topath);
unlink(frompath);
return 1;
}
from = open(frompath, O_RDONLY);
if (from < 0) {
logMessage("failed to open %s: %s", frompath, strerror(errno));
unlink(topath);
unlink(frompath);
return 1;
}
unlink(frompath);
unlink(topath);
logMessage("copying %d blocks from %s to %s", blocks, fromdev, todev);
newtCenteredWindow(60, 5, "Loading");
form = newtForm(NULL, NULL, 0);
newtFormAddComponent(form, newtLabel(1, 1, label));
scale = newtScale(1, 3, 58, blocks / LOAD_BLOCK_COUNT);
newtFormAddComponent(form, scale);
newtDrawForm(form);
newtRefresh();
for (i = 0; i < (blocks / LOAD_BLOCK_COUNT) && !rc; i++) {
newtScaleSet(scale, i);
newtRefresh();
if (read(from, buf, sizeof(buf)) != sizeof(buf)) {
logMessage("error reading from device: %s", strerror(errno));
rc = 1;
} else {
if (write(to, buf, sizeof(buf)) != sizeof(buf)) {
logMessage("error writing to device: %s", strerror(errno));
rc = 1;
}
}
}
newtPopWindow();
newtFormDestroy(form);
close(from);
close(to);
return rc;
}
static int totalMemory(void) {
int fd;
int bytesRead;
char buf[4096];
char * chptr, * start;
int total = 0;
fd = open("/proc/meminfo", O_RDONLY);
if (fd < 0) {
logMessage("failed to open /proc/meminfo: %s", strerror(errno));
return 0;
}
bytesRead = read(fd, buf, sizeof(buf) - 1);
if (bytesRead < 0) {
logMessage("failed to read from /proc/meminfo: %s", strerror(errno));
close(fd);
return 0;
}
close(fd);
buf[bytesRead] = '\0';
chptr = buf;
while (*chptr && !total) {
if (*chptr != '\n' || strncmp(chptr + 1, "MemTotal:", 9)) {
chptr++;
continue;
}
start = ++chptr ;
while (*chptr && *chptr != '\n') chptr++;
*chptr = '\0';
logMessage("found total memory tag: \"%s\"", start);
while (!isdigit(*start) && *start) start++;
if (!*start) {
logMessage("no number appears after MemTotal tag");
return 0;
}
chptr = start;
while (*chptr && isdigit(*chptr)) {
total = (total * 10) + (*chptr - '0');
chptr++;
}
}
logMessage("%d kB are available", total);
return total;
}
static int installMethodWindow(struct installMethod ** method) {
newtComponent form, listbox, okay, text;
struct installMethod * newMethod;
newtGrid grid;
char * reflowedText;
int i, width, height;
form = newtForm(NULL, NULL, 0);
reflowedText = newtReflowText("What type of media contains the packages "
"to be installed?", 30, 5, 5, &width, &height);
text = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(text, reflowedText);
free(reflowedText);
listbox = newtListbox(-1, -1, 0, NEWT_LISTBOX_RETURNEXIT);
for (i = 0; i < numMethods; i++) {
newtListboxAddEntry(listbox, methods[i].name, methods + i);
}
okay = newtButton(14, 11, "Ok");
grid = newtCreateGrid(1, 3);
newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
0, 0, 0, 0, 0, 0);
newtGridSetField(grid, 0, 1, NEWT_GRID_COMPONENT, listbox,
0, 1, 0, 0, 0, 0);
newtGridSetField(grid, 0, 2, NEWT_GRID_COMPONENT, okay,
0, 1, 0, 0, 0, 0);
newtGridWrappedWindow(grid, "Installation Method");
newtFormAddComponents(form, text, listbox, okay, NULL);
newtRunForm(form);
newMethod = newtListboxGetCurrent(listbox);
newtFormDestroy(form);
newtPopWindow();
*method = newMethod;
return 0;
}
int chooseInstallMethod(struct installMethod ** method, struct netConfig * netc,
struct netInterface * intf, struct driversLoaded ** dl) {
int rc;
if (kickstart) {
if (!ksGetCommand(KS_CMD_NFS, NULL, NULL, NULL)) {
*method = methods + NFS_METHOD_NUM;
return (*method)->prepareImage((*method), netc, intf, dl);
} else if (!ksGetCommand(KS_CMD_CDROM, NULL, NULL, NULL)) {
*method = methods + CDROM_METHOD_NUM;
return (*method)->prepareImage((*method), netc, intf, dl);
} else {
logMessage("No kickstart method was specified.");
kickstart = 0;
}
}
do {
rc = installMethodWindow(method);
if (rc) return rc;
if ((*method)->prepareImage) {
rc = (*method)->prepareImage((*method), netc, intf, dl);
if (rc == INST_ERROR) return rc;
}
} while (rc);
return 0;
}
static int nfsGetSetup(char ** hostptr, char ** dirptr) {
newtComponent form, okay, cancel, answer, text;
newtComponent siteLabel, dirLabel;
newtGrid buttons, entryArea, grid;
struct nfsMountCallbackInfo cbInfo;
char * message = "Please enter the following information:\n"
"\n"
" o the name or IP number of your NFS server\n"
" o the directory on that server containing\n"
" Red Hat Linux for your architecture";
if (*hostptr) {
cbInfo.serverVal = *hostptr;
cbInfo.netpathVal = *dirptr;
} else {
cbInfo.serverVal = "";
cbInfo.netpathVal = "";
}
form = newtForm(NULL, NULL, 0);
buttons = newtButtonBar("Ok", &okay, "Cancel", &cancel, NULL);
text = newtTextbox(-1, -1, 47, 5, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(text, message);
entryArea = newtCreateGrid(2, 2);
siteLabel = newtLabel(-1, -1, "NFS server name :");
newtGridSetField(entryArea, 0, 0, NEWT_GRID_COMPONENT, siteLabel,
0, 0, 0, 0, 0, 0);
dirLabel = newtLabel(-1, -1, "Red Hat directory:");
newtGridSetField(entryArea, 0, 1, NEWT_GRID_COMPONENT, dirLabel,
0, 0, 0, 0, 0, 0);
cbInfo.server = newtEntry(-1, -1, cbInfo.serverVal, 24, &cbInfo.serverVal,
NEWT_ENTRY_SCROLL);
newtComponentAddCallback(cbInfo.server, nfsMountCallback, &cbInfo);
cbInfo.netpath = newtEntry(-1, -1, cbInfo.netpathVal, 24,
&cbInfo.netpathVal, NEWT_ENTRY_SCROLL);
cbInfo.mntpoint = NULL;
newtGridSetField(entryArea, 1, 0, NEWT_GRID_COMPONENT, cbInfo.server,
1, 0, 0, 0, 0, 0);
newtGridSetField(entryArea, 1, 1, NEWT_GRID_COMPONENT, cbInfo.netpath,
1, 0, 0, 0, 0, 0);
grid = newtCreateGrid(1, 3);
newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text,
0, 0, 0, 0, 0, 0);
newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, entryArea,
0, 1, 0, 1, 0, 0);
newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons,
0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX);
newtGridWrappedWindow(grid, "NFS Setup");
newtFormAddComponents(form, text, cbInfo.server, cbInfo.netpath, okay,
cancel, dirLabel, siteLabel, NULL);
answer = newtRunForm(form);
if (answer == cancel) {
newtFormDestroy(form);
newtPopWindow();
return INST_CANCEL;
}
if (*hostptr) free(*hostptr);
if (*dirptr) free(*dirptr);
*hostptr = strdup(cbInfo.serverVal);
*dirptr = strdup(cbInfo.netpathVal);
newtFormDestroy(form);
newtPopWindow();
return 0;
}
static int cdromPrepare(struct installMethod * method, struct netConfig * netc,
struct netInterface * intf, struct driversLoaded ** dl) {
char * cddev;
int rc;
if (!kickstart)
newtWinMessage("Note", "Ok",
"Insert your Red Hat CD into your CD drive now");
while (1) {
/* this autoprobes already, so we don't need to do anything special
for the kickstart :-) */
rc = setupCDdevice(&cddev, dl);
if (rc) return rc;
if ((rc = loadFilesystem("iso9660", dl))) return rc;
rc = doMount(cddev, "/tmp/rhimage", "iso9660", 1, 0);
if (rc) {
removeCDmodule(dl);
newtWinMessage("Error", "Ok",
"I could not mount a CD on device /dev/%s", cddev);
continue;
}
if (access("/tmp/rhimage/RedHat", R_OK)) {
umount("/tmp/rhimage");
removeCDmodule(dl);
newtWinMessage("Error", "Ok", "That CDROM device does not seem "
"to contain a Red Hat CDROM.");
continue;
}
break;
}
if (!access("/tmp/rhimage/RedHat/instimage/lib", X_OK)) {
unlink("/tmp/rhimage/RedHat/instimage/lib");
symlink("/tmp/rhimage/RedHat/instimage/lib", "/lib");
}
if (!access("/tmp/rhimage/RedHat/instimage/usr/bin", X_OK)) {
unlink("/tmp/rhimage/RedHat/instimage/usr/bin");
symlink("/tmp/rhimage/RedHat/instimage/usr/bin", "/usr/bin");
}
return 0;
}
static int nfsPrepare(struct installMethod * method, struct netConfig * netc,
struct netInterface * intf, struct driversLoaded ** dl) {
char * host = NULL, * dir = NULL;
char * buf;
enum { NFS_STEP_NET, NFS_STEP_INFO, NFS_STEP_MOUNT, NFS_STEP_DONE }
step = NFS_STEP_NET;
int rc;
int ksArgc;
char ** ksArgv;
poptContext optCon;
struct poptOption ksNfsOptions[] = {
{ "server", '\0', POPT_ARG_STRING, &host, 0 },
{ "dir", '\0', POPT_ARG_STRING, &dir, 0 },
{ 0, 0, 0, 0, 0 }
};
if (kickstart) {
if (!intf->isConfigured || !netc->isConfigured)
if (bringUpNetworking(intf, netc, dl)) return INST_ERROR;
ksGetCommand(KS_CMD_NFS, NULL, &ksArgc, &ksArgv);
optCon = poptGetContext(NULL, ksArgc, ksArgv, ksNfsOptions, 0);
if ((rc = poptGetNextOpt(optCon)) < -1) {
newtWinMessage("nfs command", "Ok",
"bad argument to kickstart nfs command %s: %s",
poptBadOption(optCon, POPT_BADOPTION_NOALIAS),
poptStrerror(rc));
}
if (!host || !dir) {
newtWinMessage("nfs command", "Ok",
"nfs command incomplete");
} else {
step = NFS_STEP_MOUNT;
}
}
while (step != NFS_STEP_DONE) {
switch (step) {
case NFS_STEP_NET:
rc = bringUpNetworking(intf, netc, dl);
if (rc) return rc;
step = NFS_STEP_INFO;
break;
case NFS_STEP_INFO:
if (!host && getenv("BOOTP_SERVER"))
host = mygethostbyaddr(getenv("BOOTP_SERVER"));
if (!dir && getenv("BOOTP_BOOTFILE"))
dir = strdup(getenv("BOOTP_BOOTFILE"));
rc = nfsGetSetup(&host, &dir);
if (rc == INST_CANCEL)
step = NFS_STEP_NET;
else if (rc == INST_ERROR)
return INST_ERROR;
else
step = NFS_STEP_MOUNT;
break;
case NFS_STEP_MOUNT:
if (!strlen(host) || !strlen(dir))
rc = INST_ERROR;
else {
buf = malloc(strlen(host) + strlen(dir) + 10);
strcpy(buf, host);
strcat(buf, ":");
strcat(buf, dir);
if ((rc = loadFilesystem("nfs", dl))) return rc;
rc = doMount(buf, "/tmp/rhimage", "nfs", 1, 0);
free(buf);
}
if (rc) {
step = NFS_STEP_INFO;
newtWinMessage("Error", "Ok",
"I could not mount that directory from the server");
} else {
if (access("/tmp/rhimage/RedHat", R_OK)) {
step = NFS_STEP_INFO;
newtWinMessage("Error", "Ok",
"That directory does not seem "
"to contain a Red Hat installation tree.");
umount("/tmp/rhimage");
} else
step = NFS_STEP_DONE;
}
break;
case NFS_STEP_DONE:
break;
}
}
if (!kickstart) {
free(host);
free(dir);
}
if (!access("/tmp/rhimage/RedHat/instimage/lib", X_OK)) {
unlink("/tmp/rhimage/RedHat/instimage/lib");
symlink("/tmp/rhimage/RedHat/instimage/lib", "/lib");
}
if (!access("/tmp/rhimage/RedHat/instimage/usr/bin", X_OK)) {
unlink("/tmp/rhimage/RedHat/instimage/usr/bin");
symlink("/tmp/rhimage/RedHat/instimage/usr/bin", "/usr/bin");
}
return 0;
}
int floppyRoot(struct installMethod * method, struct netConfig * netc,
struct netInterface * intf, struct driversLoaded ** dl) {
return loadFloppyRoot(method,
"This install method requires a second disk. Please remove "
"the boot disk currently in your drive and replace it with "
"the Red Hat Supplementary Install disk.");
}
int loadFloppyRoot(struct installMethod * method, char * message) {
newtComponent form, text, okay, cancel, answer;
static int isMounted = 0;
if (isMounted) return 0;
if (access("/usr/bin/runinstall2", R_OK)) {
newtCenteredWindow(40, 15, "Second Floppy");
text = newtTextbox(1, 1, 38, 5, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(text, message);
okay = newtButton(6, 10, "Ok");
cancel = newtButton(24, 10, "Cancel");
form = newtForm(NULL, NULL, 0);
newtFormAddComponents(form, text, okay, cancel, NULL);
answer = newtRunForm(form);
newtFormDestroy(form);
newtPopWindow();
if (answer == cancel) return INST_CANCEL;
if (testing) return 0;
while (doMount("fd0", "/tmp/image", "ext2", 1, 0) ||
access("/tmp/image/usr/bin/runinstall2", R_OK)) {
/* in case the mount succeeded */
umount("/tmp/image");
newtCenteredWindow(40, 15, "Second Floppy");
text = newtTextbox(1, 1, 38, 5, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(text,
"I failed to mount the floppy. Please insert the "
"Red Hat Supplementary Install disk, or choose "
"Cancel to pick a different installation process.");
okay = newtButton(6, 10, "Ok");
cancel = newtButton(24, 10, "Cancel");
form = newtForm(NULL, NULL, 0);
newtFormAddComponents(form, text, okay, cancel);
answer = newtRunForm(form);
newtFormDestroy(form);
newtPopWindow();
if (answer == cancel) return INST_CANCEL;
}
if (totalMemory() > 8000) {
umount("/tmp/image");
loadRamdisk("ram2", "fd0", 1440, "Loading supplemental disk...");
if (doMount("ram2", "/tmp/image", "ext2", 1, 0)) {
errorWindow("Error mounting ramdisk. This shouldn't "
"happen, and I'm rebooting your system now.");
exit(1);
}
}
symlink("/tmp/image/lib", "/lib");
symlink("/tmp/image/etc", "/etc");
symlink("/tmp/image/usr/bin", "/usr/bin");
}
isMounted = 1;
return 0;
}