home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Chip 1998 February
/
CHIP_2_98.iso
/
misc
/
src
/
install
/
.#doit.c.1.43
< prev
next >
Wrap
Text File
|
1997-10-29
|
17KB
|
616 lines
#include <errno.h>
#include <fcntl.h>
#include <newt.h>
#include <rpmlib.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h> /* for mkdir(2) ?!? */
#include <sys/time.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <unistd.h>
#include <popt.h>
#include "kickstart.h"
#include "config.h"
#include "doit.h"
#include "install.h"
#include "kbd.h"
#include "log.h"
#include "windows.h"
extern int testing;
FILE * logFile = NULL;
static int installPackage(rpmdb db, struct installMethod * method,
struct packageInfo * pkg, int isPreskel,
int errfd, char * netSharedPath, int flags);
static void setupXfree(struct installMethod * method, rpmdb db,
struct pkgSet * psp, char * netSharedPath, int errfd);
static void setupXmetro(struct installMethod * method, rpmdb db,
struct packageInfo * pkg, char * netSharedPath,
int errfd);
static void setupX(struct installMethod * method, rpmdb db,
struct pkgSet * psp, char * netSharedPath, int errfd);
static void rpmerror(void);
static void swOpen(int numPackages, int sizePackages);
static void swPackage(Header h);
static void swPackageComplete();
static void swClose(void);
static void swCallback(const unsigned long amount, const unsigned long total);
static void formatTime(char * buf, time_t t);
int doInstall(struct installMethod * method,
struct pkgSet * psp, char * netSharedPath, char * keymap,
int upgrade) {
int i, totalNumPackages, totalSizePackages;
struct packageInfo ** orderedPackages;
int flags = 0;
rpmdb db;
int errfd;
char * logFileName = "/dev/tty5";
rpmDependencies rpmdeps, rpmorder;
char * hostEntry =
"127.0.0.1 localhost localhost.localdomain\n";
int fd;
if (testing) return 0;
mkdir("/mnt/etc", 0755);
mkdir("/mnt/tmp", 0755);
mkdir("/mnt/var", 0755);
mkdir("/mnt/var/tmp", 0755);
mkdir("/mnt/var/lib", 0755);
mkdir("/mnt/var/lib/rpm", 0755);
if (!upgrade) {
fd = open("/mnt/etc/hosts", O_CREAT | O_RDWR, 0644);
if (fd < 0) {
errorWindow("Failed to create /mnt/etc/hosts: %s.");
return INST_ERROR;
}
write(fd, hostEntry, strlen(hostEntry));
close(fd);
}
if (upgrade) {
flags |= RPMINSTALL_UPGRADE | RPMINSTALL_REPLACEFILES;
logFile = fopen("/mnt/tmp/upgrade.log", "w");
} else
logFile = fopen("/mnt/tmp/install.log", "w");
if (logFile) {
setlinebuf(logFile);
if (upgrade) {
logMessage("opened /mnt/tmp/upgrade.log");
} else {
logMessage("opened /mnt/tmp/install.log");
}
} else {
if (upgrade) {
logMessage("failed to open /mnt/tmp/upgrade.log :-(");
errorWindow("Failed to open /mnt/tmp/upgrade.log. No upgrade log "
"will be kept.");
} else {
logMessage("failed to open /mnt/tmp/install.log :-(");
errorWindow("Failed to open /mnt/tmp/install.log. No install log "
"will be kept.");
}
}
errfd = open(logFileName, O_APPEND | O_CREAT, 0644);
if (errfd < 0) {
logMessage("failed to open /dev/tty5!");
logFileName = "/tmp/exec.log";
errfd = open(logFileName, O_APPEND | O_CREAT, 0644);
if (errfd < 0) {
logMessage("failed to open %s: %s!\n", logFileName,
strerror(errno));
errfd = 2;
}
}
rpmErrorSetCallback(rpmerror);
logMessage("reading /usr/lib/rpmrc");
rpmReadConfigFiles(NULL, NULL, NULL, 0);
logMessage("\tdone");
if (rpmdbOpen("/mnt", &db, O_RDWR | O_CREAT, 0644)) {
errorWindow("Fatal error opening RPM database");
return INST_ERROR;
}
logMessage("opened rpm database");
rpmdeps = rpmdepDependencies(db);
rpmorder = rpmdepDependencies(NULL);
for (i = 0; i < psp->numPackages; i++) {
if (!strcmp(psp->packages[i]->name, "basesystem")) {
rpmdepAddPackage(rpmdeps, psp->packages[i]->h, psp->packages[i]);
rpmdepAddPackage(rpmorder, psp->packages[i]->h, psp->packages[i]);
}
}
totalNumPackages = 0, totalSizePackages = 0;
for (i = 0; i < psp->numPackages; i++) {
if (psp->packages[i]->selected) {
if (strcmp(psp->packages[i]->name, "basesystem")) {
rpmdepAddPackage(rpmdeps, psp->packages[i]->h,
psp->packages[i]);
rpmdepAddPackage(rpmorder, psp->packages[i]->h,
psp->packages[i]);
}
totalSizePackages += psp->packages[i]->size;
totalNumPackages++;
}
}
if (rpmdepOrder(rpmorder, (void ***) &orderedPackages)) {
rpmdbClose(db);
newtWinMessage("Error", "Ok", "Error ordering package list: %s",
rpmErrorString());
close(errfd);
return 1;
}
rpmdepDone(rpmdeps);
rpmdepDone(rpmorder);
if (testing) {
newtWinMessage("Status", "Ok", "Packages would be installed now");
return 0;
}
swOpen(totalNumPackages, totalSizePackages);
logMessage("installing %d packages", totalNumPackages);
for (i = 0; i < totalNumPackages; i++) {
installPackage(db, method, orderedPackages[i], 0, errfd,
netSharedPath, flags);
}
swClose();
free(orderedPackages);
#ifndef __sparc__
if (!upgrade) {
mkdir("/mnt/etc/sysconfig", 0755);
writeKbdConfig("/mnt/etc/sysconfig", keymap);
}
#endif
if (!upgrade) {
mouseConfig();
setupX(method, db, psp, netSharedPath, errfd);
}
rpmdbClose(db);
close(errfd);
if (logFile) fclose(logFile);
logMessage("rpm database closed");
return 0;
}
static int installPackage(rpmdb db, struct installMethod * method,
struct packageInfo * pkg, int isPreskel,
int errfd, char * netSharedPath, int flags) {
int fd, olderr;
char * realName;
int olderrno, rc;
if (flags & RPMINSTALL_UPGRADE) {
if (logFile)
fprintf(logFile, "Upgrading %s.\n", pkg->name);
} else {
if (logFile)
fprintf(logFile, "Installing %s.\n", pkg->name);
}
swPackage(pkg->h);
if (method->getFile(method, pkg->data, &realName, isPreskel)) {
logMessage("getFile method failed for %s", pkg->data);
if (logFile)
fprintf(logFile, "Failed to get file for package %s.\n", pkg->name);
swPackageComplete();
return 1;
}
fd = open(realName, O_RDONLY);
if (fd < 0) {
olderrno = errno;
logMessage("cannot open RPM file %s: %s", pkg->data,
strerror(olderrno));
newtWinMessage("Error", "Ok",
"Error installing package: cannot open RPM file "
"for %s: %s", pkg->data, strerror(errno));
if (logFile)
fprintf(logFile, "\tcannot open RPM file %s: %s\n",
(char *) pkg->data, strerror(olderrno));
swPackageComplete();
return 1;
}
/* this is a hack */
if (!strcmp(pkg->name, "kernel-modules"))
flags |= RPMINSTALL_NOSCRIPTS;
olderr = dup(2);
dup2(errfd, 2);
rc = rpmInstallPackage("/mnt", db, fd, NULL,
flags | RPMINSTALL_REPLACEPKG | RPMINSTALL_REPLACEFILES,
swCallback, NULL, netSharedPath);
dup2(olderr, 2);
close(olderr);
if (rc) {
olderrno = errno;
logMessage("Error installing package: package install of "
"%s failed: %s", pkg->name, rpmErrorString());
newtWinMessage("Error", "Ok", "RPM install of %s failed: %s", pkg->name,
rpmErrorString());
if (logFile)
fprintf(logFile, "\tcannot open RPM file %s: %s\n",
(char *) pkg->data, strerror(olderrno));
}
close(fd);
swPackageComplete();
if (method->rmFiles) unlink(realName);
return 0;
}
static void setupX(struct installMethod * method, rpmdb db,
struct pkgSet * psp, char * netSharedPath, int errfd) {
int hasMetro = 0, i;
newtComponent text, yes, no, form, answer;
struct packageInfo * metroPackage = NULL;
/* This is a cheap trick to see if our X component was installed */
if (access("/mnt/usr/X11R6/bin/Xconfigurator", X_OK)) {
logMessage("/mnt/usr/X11R6/bin/Xconfigurator cannot be run");
return;
}
logMessage("looking for metrox");
for (i = 0; i < psp->numPackages; i++) {
if (!strcmp(psp->packages[i]->name, "metroess")) {
logMessage("\tfound metrolink!");
metroPackage = psp->packages[i];
hasMetro = 1;
break;
}
}
if (!hasMetro || kickstart)
return setupXfree(method, db, psp, netSharedPath, errfd);
newtCenteredWindow(60, 16, "Metro-X");
text = newtTextbox(1, 1, 58, 9, NEWT_TEXTBOX_WRAP);
newtTextboxSetText(text,
"This copy of Red Hat Linux includes MetroX from MetroLink.\n\n"
"MetroX is LICENSED SOFTWARE. Your purchase of Red Hat Linux "
"entitles you to one (1) user license for this software. You "
"may not install and run MetroX on more than one computer "
"without purchasing additional licenses, which are available "
"from Red Hat Software (800) 454-5502. Would you like to install "
"MetroX on your computer?");
yes = newtButton(13, 12, "Yes");
no = newtButton(36, 12, "No");
form = newtForm(NULL, NULL, 0);
newtFormAddComponents(form, text, yes, no, NULL);
newtRunForm(form);
answer = newtFormGetCurrent(form);
newtFormDestroy(form);
newtPopWindow();
if (answer == yes) {
setupXmetro(method, db, metroPackage, netSharedPath, errfd);
} else {
setupXfree(method, db, psp, netSharedPath, errfd);
}
}
static void setupXmetro(struct installMethod * method, rpmdb db,
struct packageInfo * pkg, char * netSharedPath,
int errfd) {
int childpid;
int status;
swOpen(1, pkg->size);
installPackage(db, method, pkg, 0, errfd, netSharedPath, 0);
swClose();
symlink("../../usr/X11R6/bin/Xmetro", "/mnt/etc/X11/X");
newtSuspend();
if (!(childpid = fork())) {
chroot("/mnt");
putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin");
chdir("/");
execl("/usr/X11R6/bin/configX", "/usr/X11R6/bin/configX", NULL);
}
waitpid(childpid, &status, 0);
newtResume();
}
static void setupXfree(struct installMethod * method, rpmdb db,
struct pkgSet * psp, char * netSharedPath, int errfd) {
int fd, i;
char buf[200], * chptr;
char server[50];
int rc;
/* need proc to do pci probing */
if ((rc = doMount("/proc", "/mnt/proc", "proc", 0, 0))) {
return;
}
/* this handles kickstart and normal/expert modes */
if ((rc=xfree86Config("--pick")))
return;
#if 0
/* old pre-kickstart code */
newtSuspend();
if (!(childpid = fork())) {
chroot("/mnt");
putenv("PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/X11R6/bin");
chdir("/");
execl("/usr/X11R6/bin/Xconfigurator",
"/usr/X11R6/bin/Xconfigurator",
"--pick", NULL);
}
waitpid(childpid, &status, 0);
newtResume();
#endif
/* done with proc now */
umount("/mnt/proc");
if ((fd = open("/mnt/tmp/SERVER", O_RDONLY)) < 0) {
logMessage("failed to open /mnt/tmp/SERVER: %s", strerror(errno));
return;
}
buf[0] = '\0';
read(fd, buf, sizeof(buf));
close(fd);
chptr = buf;
while (chptr < (buf + sizeof(buf) - 1) && *chptr && *chptr != ' ')
chptr++;
if (chptr >= (buf + sizeof(buf) - 1) || *chptr != ' ') {
logMessage("couldn't find ' ' in /mnt/tmp/SERVER");
return;
}
*chptr = '\0';
strcpy(server, "XFree86-");
strcat(server, buf);
logMessage("I will install the %s package", server);
for (i = 0; i < psp->numPackages; i++) {
if (!strcmp(psp->packages[i]->name, server)) {
logMessage("\tfound package: %s", psp->packages[i]->name);
swOpen(1, psp->packages[i]->size);
installPackage(db, method, psp->packages[i], 0, errfd,
netSharedPath, 0);
swClose();
break;
}
}
/* this handles kickstart and normal/expert modes */
if ((rc=xfree86Config("--continue")))
return;
#if 0
/* pre-kickstart code */
newtSuspend();
if (!(childpid = fork())) {
chroot("/mnt");
chdir("/");
execl("/usr/X11R6/bin/Xconfigurator",
"/usr/X11R6/bin/Xconfigurator",
"--continue", NULL);
}
waitpid(childpid, &status, 0);
newtResume();
#endif
}
static void rpmerror(void) {
int code;
code = rpmErrorCode();
if (code != RPMERR_UNLINK && code != RPMERR_RMDIR) {
if (logFile)
fprintf(logFile, "%s\n", rpmErrorString());
else
logMessage(rpmErrorString());
}
}
static struct statusWindowInfo {
newtComponent form, packageLabel, sizeLabel, summaryText;
newtComponent pkgScale, globalScale;
newtComponent pkgDoneLabel, pkgRemainsLabel;
newtComponent sizeDoneLabel, sizeRemainsLabel;
newtComponent timeDoneLabel, timeRemainsLabel, timeTotalLabel;
int numPackages, packagesDone;
unsigned int sizePackages, sizeDone;
int thisPackageSize;
time_t timeStarted;
} si;
static void swOpen(int numPackages, int sizePackages) {
char buf[50];
newtCenteredWindow(60, 15, "Install Status");
si.form = newtForm(NULL, NULL, 0);
newtFormAddComponent(si.form, newtLabel(1, 1, "Package:"));
newtFormAddComponent(si.form, newtLabel(1, 2, "Size :"));
newtFormAddComponent(si.form, newtLabel(1, 3, "Summary:"));
si.packageLabel = newtLabel(13, 1, "");
si.sizeLabel = newtLabel(13, 2, "");
si.summaryText = newtTextbox(13, 3, 45, 2, NEWT_TEXTBOX_WRAP);
si.pkgScale = newtScale(3, 6, 54, 100);
newtFormAddComponent(si.form,
newtLabel(1, 8, " Packages Bytes Time"));
/* 12345678901234567890123456789012345678901234567
1 2 3 4 */
newtFormAddComponent(si.form, newtLabel(1, 9, "Total :"));
newtFormAddComponent(si.form, newtLabel(1, 10, "Completed :"));
newtFormAddComponent(si.form, newtLabel(1, 11, "Remaining :"));
si.numPackages = numPackages;
si.sizePackages = sizePackages;
si.packagesDone = 0;
si.sizeDone = 0;
si.timeStarted = time(NULL);
sprintf(buf, "%8d", numPackages);
newtFormAddComponent(si.form, newtLabel(14, 9, buf));
si.pkgDoneLabel = newtLabel(14, 10, "");
si.pkgRemainsLabel = newtLabel(14, 11, "");
sprintf(buf, "%4uM", sizePackages / (1024 * 1024));
newtFormAddComponent(si.form, newtLabel(29, 9, buf));
si.sizeDoneLabel = newtLabel(29, 10, "");
si.sizeRemainsLabel = newtLabel(29, 11, "");
si.timeTotalLabel = newtLabel(42, 9, "");
si.timeDoneLabel = newtLabel(42, 10, "");
si.timeRemainsLabel = newtLabel(42, 11, "");
si.globalScale = newtScale(1, 13, 58, sizePackages);
newtFormAddComponents(si.form, si.packageLabel, si.sizeLabel,
si.summaryText, si.pkgScale, si.globalScale,
si.pkgDoneLabel, si.pkgRemainsLabel,
si.sizeDoneLabel, si.sizeRemainsLabel,
si.timeDoneLabel, si.timeRemainsLabel,
si.timeTotalLabel, NULL);
}
static void swPackage(Header h) {
char * name, * version, * release, * summary;
char buf[50];
uint_32 * size;
headerGetEntry(h, RPMTAG_NAME, NULL, (void *) &name, NULL);
headerGetEntry(h, RPMTAG_VERSION, NULL, (void *) &version, NULL);
headerGetEntry(h, RPMTAG_RELEASE, NULL, (void *) &release, NULL);
headerGetEntry(h, RPMTAG_SIZE, NULL, (void *) &size, NULL);
if (!headerGetEntry(h, RPMTAG_SUMMARY, NULL, (void *) &summary, NULL))
summary = "(no summary)";
sprintf(buf, "%s-%s-%s", name, version, release);
newtLabelSetText(si.packageLabel, buf);
sprintf(buf, "%dk", (*size) / 1024);
newtLabelSetText(si.sizeLabel, buf);
newtTextboxSetText(si.summaryText, summary);
si.thisPackageSize = *size;
newtScaleSet(si.pkgScale, 0);
newtDrawForm(si.form);
newtRefresh();
}
static void swPackageComplete(void) {
char buf[50];
time_t now, finishTime, elapsedTime, remainingTime;
si.packagesDone++;
si.sizeDone += si.thisPackageSize;
sprintf(buf, "%8d", si.packagesDone);
newtLabelSetText(si.pkgDoneLabel, buf);
sprintf(buf, "%8d", si.numPackages - si.packagesDone);
newtLabelSetText(si.pkgRemainsLabel, buf);
sprintf(buf, "%4dM", si.sizeDone / (1024 * 1024));
newtLabelSetText(si.sizeDoneLabel, buf);
sprintf(buf, "%4dM", (si.sizePackages - si.sizeDone) / (1024 * 1024));
newtLabelSetText(si.sizeRemainsLabel, buf);
now = time(NULL);
elapsedTime = now - si.timeStarted;
formatTime(buf, elapsedTime);
newtLabelSetText(si.timeDoneLabel, buf);
finishTime = (((float) si.sizePackages) / si.sizeDone) * elapsedTime;
formatTime(buf, finishTime);
newtLabelSetText(si.timeTotalLabel, buf);
remainingTime = finishTime - elapsedTime;
formatTime(buf, remainingTime);
newtLabelSetText(si.timeRemainsLabel, buf);
newtScaleSet(si.globalScale, si.sizeDone);
newtRefresh();
}
static void swCallback(const unsigned long amount, const unsigned long total) {
if (total == 0)
newtScaleSet(si.pkgScale, 100);
else
newtScaleSet(si.pkgScale, (amount * 100) / total);
newtRefresh();
}
static void swClose(void) {
newtPopWindow();
}
static void formatTime(char * buf, time_t t) {
int hours, minutes, secs;
hours = t / 60 / 60;
t %= (60 * 60);
minutes = t / 60;
t %= 60;
secs = t;
sprintf(buf, "%01d:%02d.%02d", hours, minutes, secs);
}