summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--loader/Makefile15
-rw-r--r--loader/init.c222
-rw-r--r--loader/lang.c11
-rw-r--r--loader/loader.c200
-rw-r--r--loader/loader.h2
-rw-r--r--loader/minilibc.c9
-rw-r--r--loader/minilibc.h8
-rw-r--r--loader/misc.c29
-rw-r--r--loader/misc.h1
-rw-r--r--loader/stubs.c15
-rw-r--r--loader/telnet.c193
-rw-r--r--loader/telnet.h39
-rw-r--r--loader/telnetd.c132
-rw-r--r--loader/urls.c6
14 files changed, 626 insertions, 256 deletions
diff --git a/loader/Makefile b/loader/Makefile
index 35c57abf6..a389fee1f 100644
--- a/loader/Makefile
+++ b/loader/Makefile
@@ -29,7 +29,7 @@ MODULELINKAGE :=../isys/modutils/insmod/libmodutils.a \
../isys/modutils/util/libutil.a \
../isys/modutils/obj/libobj.a
-CFLAGS = $(DEBUG) $(OPTS) -Wall -D_GNU_SOURCE=1 -I/usr/include/kudzu -I/usr/include/rpm -I.. -DUSE_ALT_DNS=1 -DVERSION='"$(VERSION)"' -DHAVE_LIBIO_H -ggdb
+CFLAGS = $(DEBUG) $(OPTS) -ffunction-sections -Wall -D_GNU_SOURCE=1 -I/usr/include/kudzu -I/usr/include/rpm -I.. -DUSE_ALT_DNS=1 -DVERSION='"$(VERSION)"' -DHAVE_LIBIO_H -ggdb
ALLOBJS = $(OBJS) $(PCMCIAOBJS)
@@ -111,7 +111,8 @@ dirs:
install: all
mkdir -p $(DESTDIR)/$(RUNTIMEDIR)/loader
for n in $(BINS); do \
- install -s -m 755 $$n $(DESTDIR)/$(RUNTIMEDIR)/loader; \
+ install -m 755 $$n $(DESTDIR)/$(RUNTIMEDIR)/loader; \
+ strip $(DESTDIR)/$(RUNTIMEDIR)/loader/$$n; \
done
install -m 644 loader.tr $(DESTDIR)/$(RUNTIMEDIR)/loader
install -m 644 kon-loader.tr $(DESTDIR)/$(RUNTIMEDIR)/loader
@@ -126,7 +127,7 @@ loader: loader.o $(OBJS) $(NETOBJS)
$(CC) -g $(STATIC) -o $@ $^ -lpopt \
-lkudzu_loader ../isys/libisys.a ../balkan/libbalkan.a \
$(MODULELINKAGE) \
- -lpump -lbz2 -lz -lresolv -lnewt $(SLANGLIB) -lpci
+ -lpump -lz -lresolv -lnewt $(SLANGLIB) -lpci
loader-local: loader-local.o $(OBJS)
$(CC) -g $(STATIC) -o $@ $^ -lpopt \
@@ -145,13 +146,13 @@ loader-network: loader-net.o $(OBJS) $(NETOBJS)
$(CC) -g $(STATIC) -o $@ $^ -lpopt \
-lkudzu_loader ../isys/libisys.a ../balkan/libbalkan.a \
$(MODULELINKAGE) \
- -lpump -lbz2 -lz -lresolv -lnewt $(SLANGLIB) -lpci
+ -lpump -lz -lresolv -lnewt $(SLANGLIB) -lpci -lutil
loader-network-kon: loader-net-kon.o $(OBJS) $(NETOBJS)
$(CC) -g $(STATIC) -o $@ $^ -lpopt \
-lkudzu_loader ../isys/libisys.a ../balkan/libbalkan.a \
$(MODULELINKAGE) \
- -lpump -lbz2 -lz -lresolv -lnewt $(SLANGLIB) -lpci \
+ -lpump -lz -lresolv -lnewt $(SLANGLIB) -lpci -lutil \
$(KONOBJS)
loader-pcmcia: loader-pcmcia.o pcmcia.o popen.o $(OBJS) $(PCMCIAOBJS)
@@ -160,7 +161,7 @@ loader-pcmcia: loader-pcmcia.o pcmcia.o popen.o $(OBJS) $(PCMCIAOBJS)
-lpopt \
-lkudzu_loader ../isys/libisys.a ../balkan/libbalkan.a \
$(MODULELINKAGE) \
- -lpump -lbz2 -lz -lresolv -lnewt $(SLANGLIB) -lpci
+ -lpump -lz -lresolv -lnewt $(SLANGLIB) -lpci -lutil
loader-pcmcia-kon: loader-pcmcia-kon.o pcmcia.o popen.o $(OBJS) $(PCMCIAOBJS)
$(CC) -g $(STATIC) -o $@ loader-pcmcia-kon.o $(OBJS) \
@@ -168,7 +169,7 @@ loader-pcmcia-kon: loader-pcmcia-kon.o pcmcia.o popen.o $(OBJS) $(PCMCIAOBJS)
-lpopt \
-lkudzu_loader ../isys/libisys.a ../balkan/libbalkan.a \
$(MODULELINKAGE) \
- -lpump -lbz2 -lz -lresolv -lnewt $(SLANGLIB) -lpci \
+ -lpump -lz -lresolv -lnewt $(SLANGLIB) -lpci -lutil \
$(KONOBJS)
loader.o: loader.c
diff --git a/loader/init.c b/loader/init.c
index 074f067b8..1bf0aef95 100644
--- a/loader/init.c
+++ b/loader/init.c
@@ -58,6 +58,13 @@
#define syslog klogctl
#endif
+struct unmountInfo {
+ char * name;
+ int mounted;
+ int loopDevice;
+ enum { FS, LOOP } what;
+} ;
+
#include <linux/cdrom.h>
#define KICK_FLOPPY 1
@@ -315,16 +322,81 @@ int setupTerminal(int fd) {
return 0;
}
+void undoLoop(struct unmountInfo * fs, int numFs, int this);
+
+void undoMount(struct unmountInfo * fs, int numFs, int this) {
+ int len = strlen(fs[this].name);
+ int i;
+
+ if (!fs[this].mounted) return;
+ fs[this].mounted = 0;
+
+ /* unmount everything underneath this */
+ for (i = 0; i < numFs; i++) {
+ if (fs[i].name[len] == '/' &&
+ !strncmp(fs[this].name, fs[i].name, len)) {
+ if (fs[i].what == LOOP)
+ undoLoop(fs, numFs, i);
+ else
+ undoMount(fs, numFs, i);
+ }
+ }
+
+ printf("\t%s", fs[this].name);
+ /* don't need to unmount /tmp. it is busy anyway. */
+ if (!testing) {
+ if (umount(fs[this].name) < 0) {
+ printf(" umount failed (%d)", errno);
+ } else {
+ printf(" done");
+ }
+ }
+ printf("\n");
+}
+
+void undoLoop(struct unmountInfo * fs, int numFs, int this) {
+ int i;
+ int fd;
+
+ if (!fs[this].mounted) return;
+ fs[this].mounted = 0;
+
+ /* find the device mount */
+ for (i = 0; i < numFs; i++) {
+ if (fs[i].what == FS && (fs[i].loopDevice == fs[this].loopDevice))
+ break;
+ }
+
+ if (i < numFs) {
+ /* the device is mounted, unmount it (and recursively, anything
+ * underneath) */
+ undoMount(fs, numFs, i);
+ }
+
+ unlink("/tmp/loop");
+ mknod("/tmp/loop", 0600 | S_IFBLK, (7 << 8) | fs[this].loopDevice);
+ printf("\tdisabling /dev/loop%d", fs[this].loopDevice);
+ if ((fd = open("/tmp/loop", O_RDONLY, 0)) < 0) {
+ printf(" failed to open device: %d", errno);
+ } else {
+ if (!testing && ioctl(fd, LOOP_CLR_FD, 0))
+ printf(" LOOP_CLR_FD failed: %d", errno);
+ close(fd);
+ }
+
+ printf("\n");
+}
+
void unmountFilesystems(void) {
int fd, size;
char buf[65535]; /* this should be big enough */
char * chptr, * start;
- struct {
- char * name;
- int len;
- } filesystems[500], tmp;
+ struct unmountInfo filesystems[500];
int numFilesystems = 0;
- int i, j;
+ int i;
+ struct loop_info li;
+ char * device;
+ struct stat sb;
fd = open("/proc/mounts", O_RDONLY, 0);
if (fd < 1) {
@@ -341,39 +413,61 @@ void unmountFilesystems(void) {
chptr = buf;
while (*chptr) {
+ device = chptr;
while (*chptr != ' ') chptr++;
- chptr++;
+ *chptr++ = '\0';
start = chptr;
while (*chptr != ' ') chptr++;
*chptr++ = '\0';
- filesystems[numFilesystems].name = start;
- filesystems[numFilesystems].len = strlen(start);
- numFilesystems++;
+
+ if (strcmp(start, "/") && strcmp(start, "/tmp")) {
+ filesystems[numFilesystems].name = alloca(strlen(start) + 1);
+ strcpy(filesystems[numFilesystems].name, start);
+ filesystems[numFilesystems].what = FS;
+ filesystems[numFilesystems].mounted = 1;
+
+ stat(start, &sb);
+ if ((sb.st_dev >> 8) == 7) {
+ filesystems[numFilesystems].loopDevice = sb.st_dev & 0xf;
+ } else {
+ filesystems[numFilesystems].loopDevice = -1;
+ }
+
+ numFilesystems++;
+ }
+
while (*chptr != '\n') chptr++;
chptr++;
}
- /* look ma, a *bubble* sort */
- for (i = 0; i < (numFilesystems - 1); i++) {
- for (j = i; j < numFilesystems; j++) {
- if (filesystems[i].len < filesystems[j].len) {
- tmp = filesystems[i];
- filesystems[i] = filesystems[j];
- filesystems[j] = tmp;
+ for (i = 0; i < 7; i++) {
+ unlink("/tmp/loop");
+ mknod("/tmp/loop", 0600 | S_IFBLK, (7 << 8) | i);
+ if ((fd = open("/tmp/loop", O_RDONLY, 0)) >= 0) {
+ if (!ioctl(fd, LOOP_GET_STATUS, &li) && li.lo_name[0]) {
+ filesystems[numFilesystems].name = alloca(strlen(li.lo_name)
+ + 1);
+ strcpy(filesystems[numFilesystems].name, li.lo_name);
+ filesystems[numFilesystems].what = LOOP;
+ filesystems[numFilesystems].mounted = 1;
+ filesystems[numFilesystems].loopDevice = i;
+ numFilesystems++;
}
+
+ close(fd);
}
}
- /* -1 because the last one will always be '/' */
- for (i = 0; i < numFilesystems - 1; i++) {
- printf("\t%s", filesystems[i].name);
- /* don't need to unmount /tmp. it is busy anyway. */
- if (!testing && strncmp(filesystems[i].name, "/tmp", 4)) {
- if (umount(filesystems[i].name) < 0) {
- printf(" umount failed (%d)", errno);
- }
+ for (i = 0; i < numFilesystems; i++) {
+ if (filesystems[i].what == LOOP) {
+ undoLoop(filesystems, numFilesystems, i);
+ }
+ }
+
+ for (i = 0; i < numFilesystems; i++) {
+ if (filesystems[i].mounted) {
+ undoMount(filesystems, numFilesystems, i);
}
- printf("\n");
}
}
@@ -411,74 +505,6 @@ void disableSwap(void) {
}
}
-int handleCleanup(void) {
- int i;
- char buf[4096];
- int fd;
- int loopfd, ejectfd;
- char * start, * end;
-
- fd = open("/tmp/cleanup", O_RDONLY, 0);
- if (fd < 0) return 1;
-
- i = read(fd, buf, sizeof(buf) - 1);
- buf[i] = '\0';
- close(fd);
-
- start = buf;
- while (*start) {
- end = start;
- while (*end && *end != '\n') end++;
- if (!*end) return 0;
- *end = '\0';
-
- if (!strncmp(start, "lounsetup ", 10)) {
- start += 10;
- while (isspace(*start) && start < end) start++;
- if (start == end) return 1;
-
- loopfd = open(start, O_RDONLY, 0);
- if (loopfd < 0) {
- printf("\terror opening %s: %d\n", start, errno);
- } else {
- printf("disabling %s", start);
- if (ioctl(loopfd, LOOP_CLR_FD, 0))
- printf(" failed: %d", errno);
- printf("\n");
- }
-
- close(loopfd);
- } else if (!strncmp(start, "umount ", 7)) {
- start += 7;
- while (isspace(*start) && start < end) start++;
- if (start == end) return 1;
-
- printf("unmounting %s...", start);
- if (umount(start) < 0)
- printf(" failed (%d)", errno);
- printf("\n");
- } else if (!strncmp(start, "eject ", 6)) {
- start += 6;
- while (isspace(*start) && start < end) start++;
- if (start == end) return 1;
-
- printf("ejecting %s...", start);
- if ((ejectfd = open(start, O_RDONLY | O_NONBLOCK, 0)) >= 0) {
- if (ioctl(ejectfd, CDROMEJECT, 0))
- printf("eject failed %d ", errno);
-
- close(ejectfd);
- }
-
- printf("\n");
- }
-
- start = end + 1;
- }
-
- return 0;
-}
-
int main(int argc, char **argv) {
pid_t installpid, childpid;
int waitStatus;
@@ -507,6 +533,14 @@ int main(int argc, char **argv) {
printstr("(running in test mode).\n");
}
+#if 0
+ printf("unmounting filesystems...\n");
+ unmountFilesystems();
+ exit(0);
+#endif
+
+ umask(022);
+
printstr("Greetings.\n");
printf("Red Hat install init version %s starting\n", VERSION);
@@ -701,8 +735,6 @@ int main(int argc, char **argv) {
printf("disabling swap...\n");
disableSwap();
- handleCleanup();
-
printf("unmounting filesystems...\n");
unmountFilesystems();
diff --git a/loader/lang.c b/loader/lang.c
index 1effb6d44..8f4a3900b 100644
--- a/loader/lang.c
+++ b/loader/lang.c
@@ -37,6 +37,9 @@ struct aString {
struct aString * strings = NULL;
int numStrings = 0, allocedStrings = 0;
+static char * topLineWelcome = N_("Welcome to Red Hat Linux");
+static char * bottomHelpLine = N_(" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen ");
+
static int aStringCmp(const void * a, const void * b) {
const struct aString * first = a;
const struct aString * second = b;
@@ -305,6 +308,10 @@ int chooseLanguage(char ** lang, int flags) {
free(strings), strings = NULL;
numStrings = allocedStrings = 0;
}
+
+ newtDrawRootText(0, 0, _(topLineWelcome));
+ newtPushHelpLine(_(bottomHelpLine));
+
return 0;
}
@@ -341,8 +348,8 @@ int chooseLanguage(char ** lang, int flags) {
if (languages[choice].map)
loadFont(languages[choice].map, flags);
- newtDrawRootText(0, 0, _("Welcome to Red Hat Linux"));
- newtPushHelpLine(_(" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen "));
+ newtDrawRootText(0, 0, _(topLineWelcome));
+ newtPushHelpLine(_(bottomHelpLine));
return 0;
}
diff --git a/loader/loader.c b/loader/loader.c
index ebb410bdb..7c9558e32 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -164,6 +164,7 @@ static void startNewt(int flags) {
void stopNewt(void) {
if (newtRunning) newtFinished();
+ newtRunning = 0;
}
static void spawnShell(int flags) {
@@ -427,106 +428,22 @@ int busProbe(moduleInfoSet modInfo, moduleList modLoaded, moduleDeps modDeps,
return 0;
}
-static int loadCompressedRamdisk(int fd, off_t size, char *title,
- char *ramdisk, int flags) {
- int rc = 0, ram, i;
- gzFile stream;
- char buf[1024];
- newtComponent form = NULL, scale = NULL;
- int total;
-
- if (FL_TESTING(flags)) return 0;
-
- stream = gzdopen(dup(fd), "r");
-
- strcpy(buf, "/tmp/");
- strcat(buf, ramdisk);
-
- if (devMakeInode(ramdisk, buf)) return 1;
- ram = open(buf, O_WRONLY);
- unlink(buf);
-
- logMessage("created inode");
-
- if (title != NULL) {
- if (size > 0)
- newtCenteredWindow(70, 5, _("Loading"));
- else
- newtCenteredWindow(70, 3, _("Loading"));
-
- form = newtForm(NULL, NULL, 0);
-
- newtFormAddComponent(form, newtLabel(1, 1, title));
- if (size > 0) {
- scale = newtScale(1, 3, 68, size);
- newtFormAddComponent(form, scale);
- }
- newtDrawForm(form);
- newtRefresh();
- }
-
- total = 0;
- while (!gzeof(stream) && !rc) {
- if ((i = gzread(stream, buf, sizeof(buf))) != sizeof(buf)) {
- if (!gzeof(stream)) {
- logMessage("error reading from device: %s", strerror(errno));
- rc = 1;
- break;
- }
- }
-
- if (write(ram, buf, i) != i) {
- logMessage("error writing to device: %s", strerror(errno));
- rc = 1;
- }
-
- total += i;
-
- if (title != NULL && size > 0) {
- newtScaleSet(scale, lseek(fd, 0L, SEEK_CUR));
- newtRefresh();
- }
- }
-
- logMessage("done loading %d bytes", total);
-
- memoryOverhead += (total / 1024);
-
- if (title != NULL) {
- newtPopWindow();
- newtFormDestroy(form);
- }
-
- close(ram);
- gzclose(stream);
-
- return rc;
-}
-
-static int loadStage2Ramdisk(int fd, off_t size, int flags,
+static int setupStage2Image(int fd, char * dest, int flags,
char * device, char * mntpoint) {
int rc;
- char * buf;
- char * message = N_("Loading %s ramdisk...");
+ struct stat sb;
- message = _(message);
+ rc = copyFileFd(fd, dest);
+ stat(dest, &sb);
+ logMessage("copied %d bytes to %s", sb.st_size, dest);
- buf = alloca(strlen(message) + strlen(mntpoint) + 20);
- sprintf(buf, message, mntpoint);
-
- rc = loadCompressedRamdisk(fd, size, buf, device, flags);
-
if (rc) {
- newtWinMessage(_("Error"), _("OK"), _("Error loading ramdisk."));
- return rc;
- }
-
- if (devMakeInode(device, "/tmp/ram")) {
- logMessage("failed to make device %s", device);
+ /* just to make sure */
+ unlink(dest);
return 1;
}
-
- if (doPwMount("/tmp/ram", mntpoint, "ext2", 0, 0, NULL, NULL)) {
+
+ if (mountLoopback(dest, mntpoint, device)) {
newtWinMessage(_("Error"), _("OK"),
"Error mounting /dev/%s on %s (%s). This shouldn't "
"happen, and I'm rebooting your system now.",
@@ -534,28 +451,26 @@ static int loadStage2Ramdisk(int fd, off_t size, int flags,
exit(1);
}
- unlink("/tmp/ram");
-
return 0;
}
#ifdef INCLUDE_LOCAL
-static int loadSingleImage(char * prefix, char * dir, char * file, int flags,
+static int loadLocalImages(char * prefix, char * dir, int flags,
char * device, char * mntpoint) {
int fd, rc;
char * path;
- path = alloca(50 + strlen(file) + strlen(prefix) +
- (dir ? strlen(dir) : 2));
+ path = alloca(50 + strlen(prefix) + (dir ? strlen(dir) : 2));
- sprintf(path, "%s/%s/%s", prefix, dir ? dir : "", file);
+ sprintf(path, "%s/%s/RedHat/base/hdstg1.img", prefix, dir ? dir : "");
if ((fd = open(path, O_RDONLY)) < 0) {
logMessage("failed to open %s: %s", path, strerror(errno));
return 1;
}
- rc = loadStage2Ramdisk(fd, 0, flags, device, mntpoint);
+ rc = setupStage2Image(fd, "/tmp/ramfs/hdstg1.img", flags, device, mntpoint);
+
close(fd);
return rc;
@@ -603,18 +518,11 @@ static char * setupIsoImages(char * device, char * type, char * dirName,
continue;
}
- rc = loadSingleImage("/tmp/loopimage", "/",
- "RedHat/base/hdstg1.img",
- flags, "ram3", "/mnt/runtime");
- if (!rc) {
- rc = loadSingleImage("/tmp/loopimage", "/",
- "RedHat/base/hdstg2.img",
- flags, "ram4", "/mnt/runtime/usr");
- if (!rc) {
- umountLoopback("/tmp/loopimage", "loop0");
- break;
- }
-
+ rc = loadLocalImages("/tmp/loopimage", "/", flags, "loop0",
+ "/mnt/runtime");
+ if (!rc) {
+ umountLoopback("/tmp/loopimage", "loop0");
+ break;
}
umountLoopback("/tmp/loopimage", "loop0");
@@ -649,13 +557,9 @@ static char * setupOldHardDrive(char * device, char * type, char * dir,
if (doPwMount("/tmp/hddev", "/tmp/hdimage", type, 1, 0, NULL, NULL))
return NULL;
- rc = loadSingleImage("/tmp/hdimage", dir, "RedHat/base/hdstg1.img",
- flags, "ram3", "/mnt/runtime");
- if (!rc) {
- rc = loadSingleImage("/tmp/hdimage", dir, "RedHat/base/hdstg2.img",
- flags, "ram4", "/mnt/runtime/usr");
- if (rc) umount("/mnt/hdimage");
- }
+ rc = loadLocalImages("/tmp/hdimage", dir, flags, "loop0",
+ "/mnt/runtime");
+ if (rc) umount("/mnt/hdimage");
umount("/tmp/hdimage");
@@ -1108,6 +1012,8 @@ static int ensureNetDevice(struct knownDevices * kd,
return 0;
}
+ startNewt(flags);
+
deviceNum = 0;
rc = newtWinMenu(_("Networking Device"),
_("You have multiple network devices on this system. "
@@ -1217,7 +1123,7 @@ static char * mountNfsImage(struct installMethod * method,
#ifdef INCLUDE_NETWORK
static int loadSingleUrlImage(struct iurlinfo * ui, char * file, int flags,
- char * device, char * mntpoint) {
+ char * dest, char * mntpoint, char * device) {
int fd;
int rc;
@@ -1226,32 +1132,23 @@ static int loadSingleUrlImage(struct iurlinfo * ui, char * file, int flags,
if (fd < 0)
return 1;
- rc = loadStage2Ramdisk(fd, 0, flags, device, mntpoint);
- urlinstFinishTransfer(ui, fd);
+ rc = setupStage2Image(fd, dest, flags, device, mntpoint);
- if (rc) return 1;
+ urlinstFinishTransfer(ui, fd);
- return 0;
+ return rc;
}
static int loadUrlImages(struct iurlinfo * ui, int flags) {
- if (loadSingleUrlImage(ui, "base/netstg1.img", flags, "ram3",
- "/mnt/runtime")) {
+ if (loadSingleUrlImage(ui, "base/netstg1.img", flags,
+ "/tmp/ramfs/netstg1.img",
+ "/mnt/runtime", "loop0")) {
newtWinMessage(ui->protocol == URL_METHOD_FTP ?
_("FTP") : _("HTTP"), _("OK"),
_("Unable to retrieve the first install image"));
return 1;
}
- if (loadSingleUrlImage(ui, "base/netstg2.img", flags, "ram4",
- "/mnt/runtime/usr")) {
- umount("/mnt/runtime");
- newtWinMessage(ui->protocol == URL_METHOD_FTP ?
- _("FTP") : _("HTTP"), _("OK"),
- _("Unable to retrieve the second install image"));
- return 1;
- }
-
return 0;
}
@@ -1924,6 +1821,8 @@ static int parseCmdLineFlags(int flags, char * cmdLine, char ** ksSource,
for (i = 0; i < argc; i++) {
if (!strcasecmp(argv[i], "expert"))
flags |= LOADER_FLAGS_EXPERT | LOADER_FLAGS_MODDISK;
+ else if (!strcasecmp(argv[i], "telnet"))
+ flags |= LOADER_FLAGS_TELNETD;
else if (!strcasecmp(argv[i], "noshell"))
flags |= LOADER_FLAGS_NOSHELL;
else if (!strcasecmp(argv[i], "lowres"))
@@ -2455,7 +2354,7 @@ static void checkForRam(int flags) {
if (!FL_EXPERT(flags) && (totalMemory() < MIN_RAM)) {
startNewt(flags);
newtWinMessage(_("Error"), _("OK"), _("You do not have enough "
- "system memory to install Red Hat Linux on this machine."));
+ "RAM to install Red Hat Linux on this machine."));
stopNewt();
exit(0);
}
@@ -2570,8 +2469,11 @@ int main(int argc, char ** argv) {
mlLoadDeps(&modDeps, "/modules/modules.dep");
mlLoadModule("cramfs", NULL, modLoaded, modDeps, NULL, modInfo, flags);
+ mlLoadModule("ramfs", NULL, modLoaded, modDeps, NULL, modInfo, flags);
if (!continuing) {
+ doPwMount("/tmp/ramfs", "/tmp/ramfs", "ramfs", 0, 0, NULL, NULL);
+
ideSetup(modLoaded, modDeps, modInfo, flags, &kd);
scsiSetup(modLoaded, modDeps, modInfo, flags, &kd);
@@ -2622,9 +2524,8 @@ int main(int argc, char ** argv) {
#endif
if (!continuing) {
- if (((access("/proc/bus/pci/devices", X_OK) &&
- access("/proc/openprom", X_OK)) || FL_MODDISK(flags))
- && !ksFile) {
+ if ((access("/proc/bus/pci/devices", X_OK) &&
+ access("/proc/openprom", X_OK)) || FL_MODDISK(flags)) {
startNewt(flags);
devLoadDriverDisk(modInfo, modLoaded, &modDeps, flags, 1, 1,
floppyDevice);
@@ -2669,6 +2570,27 @@ int main(int argc, char ** argv) {
&flags, ksNetDevice);
}
+#ifdef INCLUDE_NETWORK
+ if (FL_TELNETD(flags)) {
+ struct networkDeviceConfig netDev;
+
+ if (!ksNetDevice) {
+ if (ensureNetDevice(&kd, modInfo, modLoaded, &modDeps, flags,
+ &ksNetDevice))
+ return 1;
+ }
+
+ kickstartNetwork(&ksNetDevice, &netDev, NULL, flags);
+ writeNetInfo("/tmp/netinfo", &netDev, &kd);
+
+ stopNewt();
+#if 0
+ beTelnet();
+#endif
+ startNewt(flags);
+ }
+#endif
+
if (!url) {
url = doMountImage("/mnt/source", &kd, modInfo, modLoaded, &modDeps,
&lang, &keymap, &kbdtype,
diff --git a/loader/loader.h b/loader/loader.h
index bbe8e8c5a..00573a00f 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -25,6 +25,7 @@
#define LOADER_FLAGS_NOFB (1 << 19)
#define LOADER_FLAGS_NOPCMCIA (1 << 20)
#define LOADER_FLAGS_RESCUE_NOMOUNT (1 << 21)
+#define LOADER_FLAGS_TELNETD (1 << 22)
#define FL_TESTING(a) ((a) & LOADER_FLAGS_TESTING)
#define FL_EXPERT(a) ((a) & LOADER_FLAGS_EXPERT)
@@ -48,6 +49,7 @@
#define FL_NOFB(a) ((a) & LOADER_FLAGS_NOFB)
#define FL_NOPCMCIA(a) ((a) & LOADER_FLAGS_NOPCMCIA)
#define FL_RESCUE_NOMOUNT(a) ((a) & LOADER_FLAGS_RESCUE_NOMOUNT)
+#define FL_TELNETD(a) ((a) & LOADER_FLAGS_TELNETD)
#define CODE_PCMCIA 1
diff --git a/loader/minilibc.c b/loader/minilibc.c
index 6ae12c7a0..3103855bc 100644
--- a/loader/minilibc.c
+++ b/loader/minilibc.c
@@ -6,8 +6,8 @@ int atexit (void (*__func) (void)) {
return 0;
}
-void exit() {
- _do_exit(0);
+void exit(int arg) {
+ _do_exit(arg);
for (;;); /* Shut up gcc */
}
@@ -138,6 +138,11 @@ void printint(int i) {
char * chptr = buf + 9;
int j = 0;
+ if (!i) {
+ write(1, "0", 1);
+ return;
+ }
+
if (i < 0) {
write(1, "-", 1);
i = -1 * i;
diff --git a/loader/minilibc.h b/loader/minilibc.h
index b0abe58e3..c774e92b2 100644
--- a/loader/minilibc.h
+++ b/loader/minilibc.h
@@ -10,6 +10,7 @@
#define WTERMSIG(status) ((status) & 0x7f)
#define WSTOPSIG(status) WEXITSTATUS(status)
#define WIFEXITED(status) (WTERMSIG(status) == 0)
+#define S_IFBLK 0060000
#define MS_MGC_VAL 0xc0ed0000
@@ -35,6 +36,10 @@ extern int errno;
#include <asm/unistd.h>
#include <asm/fcntl.h>
#include <asm/signal.h>
+#include <asm/stat.h>
+
+void * alloca(int size);
+void exit(int arg);
#ifndef MINILIBC_INTERNAL
static inline _syscall5(int,mount,const char *,spec,const char *,dir,const char *,type,unsigned long,rwflag,const void *,data);
@@ -46,6 +51,7 @@ static inline _syscall3(int,execve,const char *,fn,void *,argv,void *,envp)
static inline _syscall3(int,read,int,fd,const char *,buf,unsigned long,count)
static inline _syscall3(int,open,const char *,fn,int,flags,mode_t,mode)
static inline _syscall3(int,ioctl,int,fd,int,request,void *,argp)
+static inline _syscall3(int,mknod,char *,path,int,mode,short,dev)
static inline _syscall2(int,dup2,int,one,int,two)
static inline _syscall2(int,kill,pid_t,pid,int,sig)
static inline _syscall2(int,symlink,const char *,a,const char *,b)
@@ -54,10 +60,12 @@ static inline _syscall2(int,sethostname,const char *,name,int,len)
static inline _syscall2(int,setdomainname,const char *,name,int,len)
static inline _syscall2(int,setpgid,int,name,int,len)
static inline _syscall2(int,signal,int,num,void *,len)
+static inline _syscall2(int,stat,const char *,file,struct stat *,buf)
static inline _syscall1(int,umount,const char *,dir)
static inline _syscall1(int,unlink,const char *,fn)
static inline _syscall1(int,close,int,fd)
static inline _syscall1(int,swapoff,const char *,fn)
+static inline _syscall1(int,umask,int,mask)
static inline _syscall0(int,getpid)
static inline _syscall0(int,getppid)
static inline _syscall0(int,sync)
diff --git a/loader/misc.c b/loader/misc.c
index 776520a0e..13f727a04 100644
--- a/loader/misc.c
+++ b/loader/misc.c
@@ -5,19 +5,15 @@
#include "log.h"
-int copyFile(char * source, char * dest) {
- int infd = -1, outfd = -1;
+int copyFileFd(int infd, char * dest) {
+ int outfd;
char buf[4096];
int i;
int rc = 0;
outfd = open(dest, O_CREAT | O_RDWR, 0666);
- infd = open(source, O_RDONLY);
- if (infd < 0) {
- logMessage("failed to open %s: %s", source, strerror(errno));
- return 1;
- } else if (outfd < 0) {
+ if (outfd < 0) {
close(infd);
logMessage("failed to open %s: %s", dest, strerror(errno));
return 1;
@@ -30,12 +26,29 @@ int copyFile(char * source, char * dest) {
}
}
- close(infd);
close(outfd);
return rc;
}
+int copyFile(char * source, char * dest) {
+ int infd = -1;
+ int rc;
+
+ infd = open(source, O_RDONLY);
+
+ if (infd < 0) {
+ logMessage("failed to open %s: %s", source, strerror(errno));
+ return 1;
+ }
+
+ rc = copyFileFd(infd, dest);
+
+ close(infd);
+
+ return rc;
+}
+
char * readLine(FILE * f) {
char buf[1024];
diff --git a/loader/misc.h b/loader/misc.h
index b85f140db..ce4b39b73 100644
--- a/loader/misc.h
+++ b/loader/misc.h
@@ -2,6 +2,7 @@
#define H_LOADER_MISC_H
int copyFile(char * source, char * dest);
+int copyFileFd(int infd, char * dest);
char * readLine(FILE * f);
#endif
diff --git a/loader/stubs.c b/loader/stubs.c
index 4dc969d90..c4791a38c 100644
--- a/loader/stubs.c
+++ b/loader/stubs.c
@@ -102,5 +102,20 @@ int _dl_aux_init() { return 0;}
void * __libc_dlopen() {return 0;}
void * __libc_dlsym() {return 0;}
void * __libc_dlclose() {return 0;}
+int __argz_create_sep() {return 0;}
+int __argz_add_sep() {return 0;}
+void __rpc_thread_key_cleanup() {}
+void __rpc_thread_svc_cleanup() {}
+void __rpc_thread_clnt_cleanup() {}
+void _svcauth_des(void * a, void * b) {}
+
+int getdomainname(char * name, int len) {
+ *name = '\0';
+ return 0;
+}
+
+int _rpc_dtablesize(void) {
+ return __getdtablesize();
+}
int _dl_pagesize = 4096;
diff --git a/loader/telnet.c b/loader/telnet.c
new file mode 100644
index 000000000..bf53476aa
--- /dev/null
+++ b/loader/telnet.c
@@ -0,0 +1,193 @@
+/* telnet.c -- basic telnet protocol handling for ttywatch
+ *
+ * Copyright © 2001 Michael K. Johnson <johnsonm@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+/* Shamelessly stolen from ttywatch -- oot */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "telnet.h"
+#include "log.h"
+
+#define IAC "\xff"
+#define DONT "\xfe"
+#define WONT "\xfc"
+#define WILL "\xfb"
+#define DO "\xfd"
+#define SB "\xfa"
+#define SE "\xf0"
+#define ECHO "\x01"
+#define SUPPRESS_GO_AHEAD "\x03"
+#define LINEMODE "\x22"
+#define NEWENVIRON "\x27"
+#define MODE "\x01"
+
+/* Make a request. Not intended to be RFC-compatible, just enough
+ * to convince telnet clients to do what we want... To do this
+ * right, we would have to honestly negotiate, not speak blind.
+ *
+ * For now, assume all responses will be favorable and stripped
+ * out in telnet_process_input()... Sending it all in a single
+ * write makes it more efficient because it will all go out in a
+ * single packet, and the responses are more likely to all come
+ * back in a single packet (and thus, practically, a single read)
+ * too.
+ */
+void
+telnet_negotiate(int socket) {
+ char request[]=
+ IAC DONT ECHO
+ IAC WILL ECHO
+ IAC WILL SUPPRESS_GO_AHEAD
+ IAC DO SUPPRESS_GO_AHEAD
+ IAC DONT NEWENVIRON
+ IAC WONT NEWENVIRON
+ IAC DO LINEMODE
+ IAC SB LINEMODE MODE "0" IAC SE
+ ;
+ write(socket, request, sizeof(request)-1);
+}
+
+int
+telnet_process_input(telnet_state * ts, char *data, int len) {
+ char *s, *d; /* source, destination */
+
+# define DEBUG_TELNET 0
+# if DEBUG_TELNET
+ printf("\nprinting packet:");
+ for (s=data; s<data+len; s++) {
+ if (!((s-data)%10))
+ printf("\n %03d: ", s-data);
+ printf("%02x ", *s & 0x000000FF);
+ }
+ printf("\n");
+# endif /* DEBUG_TELNET */
+
+ for (s=data, d=data; s<data+len; s++) {
+ switch (*ts) {
+ case TS_DATA:
+ if (*s == '\xff') { /* IAC */
+ *ts = TS_IAC;
+ continue;
+ }
+#if DEBUG_TELNET
+ printf("copying data element '%c'\n", *s);
+#endif /* DEBUG_TELNET */
+ if (s>d) {
+ *(d++) = *s;
+ } else {
+ d++;
+ }
+ break;
+
+ case TS_IAC:
+ if (*s == '\xfa') { /* SB */
+ *ts = TS_SB;
+ continue;
+ }
+ /* if not SB, skip IAC verb object */
+# if DEBUG_TELNET
+ printf("skipping verb/object (offset %d)...\n", s-data-1);
+# endif /* DEBUG_TELNET */
+ s += 1;
+ *ts = TS_DATA;
+ break;
+
+ case TS_SB:
+# if DEBUG_TELNET
+ printf("skipping SB (offset %d)...\n", s-data-1);
+# endif /* DEBUG_TELNET */
+ while (s < (data+(len-1))) {
+ if (*s == '\xff') {
+ break; /* fall through to TS_SB_IAC setting below */
+ } else {
+ s++;
+ }
+ }
+ if (*s == '\xff') {
+ *ts = TS_SB_IAC;
+ }
+ break;
+
+ case TS_SB_IAC:
+ if (*s == '\xf0') { /* SE */
+# if DEBUG_TELNET
+ printf("SE ends SB (offset %d)...\n", s-data-1);
+# endif /* DEBUG_TELNET */
+ *ts = TS_DATA;
+ } else {
+# if DEBUG_TELNET
+ printf("IAC without SE in SB\n");
+# endif /* DEBUG_TELNET */
+ *ts = TS_SB;
+ }
+ break;
+
+ default:
+ logMessage("unknown telnet state %d for data element %c", *ts, *s);
+ *ts = TS_DATA;
+ break;
+ }
+ }
+
+ /* calculate new length after copying data around */
+ len = d - data;
+#if DEBUG_TELNET
+ printf("returning len: %d of packet:", len);
+ for (s=data; s<data+len; s++) {
+ if (!((s-data)%10))
+ printf("\n %03d: ", s-data);
+ printf("%02x ", *s & 0x000000FF);
+ }
+ printf("\n");
+#endif /* DEBUG_TELNET */
+ return len;
+}
+
+/* The telnet protocol requires CR/NL instead of just NL
+ * We normally deal with Unix, which just uses NL, so we need to translate.
+ *
+ * It would be easy to go through line-by-line and write each line, but
+ * that would create more packet overhead by sending out one packet
+ * per line, and over things like slow PPP connections, that is painful.
+ * Therefore, instead, we create a modified copy of the data and write
+ * the whole modified copy at once.
+ */
+void
+telnet_send_output(int sock, char *data, int len) {
+ char *s, *d; /* source, destination */
+ char *buf;
+
+ buf = alloca((len*2)+1); /* max necessary size */
+
+ /* just may need to add CR before NL (but do not double existing CRs) */
+ for (s=data, d=buf; d-buf<len; s++, d++) {
+ if ((*s == '\n') && (s == data || (*(s-1) != '\r'))) {
+ /* NL without preceding CR */
+ *(d++) = '\r';
+ len++;
+ }
+ *d = *s;
+ }
+
+ /* now send it... */
+ write(sock, buf, len);
+}
diff --git a/loader/telnet.h b/loader/telnet.h
new file mode 100644
index 000000000..f43ed2b65
--- /dev/null
+++ b/loader/telnet.h
@@ -0,0 +1,39 @@
+/* telnet.h -- basic telnet protocol handling for ttywatch
+ *
+ * Copyright © 2001 Michael K. Johnson <johnsonm@redhat.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+
+#ifndef __TELNET_H__
+#define __TELNET_H__
+
+typedef enum {
+ TS_DATA = 0,
+ TS_IAC,
+ TS_SB,
+ TS_SB_IAC,
+} telnet_state;
+
+void
+telnet_negotiate(int socket);
+int
+telnet_process_input(telnet_state * ts, char *data, int len);
+void
+telnet_send_output(int sock, char *data, int len);
+
+#endif /* __TELNET_H__ */
diff --git a/loader/telnetd.c b/loader/telnetd.c
new file mode 100644
index 000000000..d1ae82fa1
--- /dev/null
+++ b/loader/telnetd.c
@@ -0,0 +1,132 @@
+/* Glue to tie telnet.c from ttywatch to the loader */
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <pty.h>
+#include <string.h>
+#include <sys/poll.h>
+#include <sys/signal.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <termios.h>
+#include <unistd.h>
+
+#include "log.h"
+#include "telnet.h"
+
+/* Forks, keeping the loader as our child (so we know when it dies). */
+int beTelnet(void) {
+ int sock;
+ int conn;
+ int addrLength;
+ pid_t child;
+ int i;
+ int masterFd;
+ struct sockaddr_in address;
+ char buf[4096];
+ struct pollfd fds[3];
+ telnet_state ts = TS_DATA;
+ struct termios orig, new;
+
+ if ((sock = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
+ logMessage("socket: %s", strerror(errno));
+ return -1;
+ }
+
+ address.sin_family = AF_INET;
+ address.sin_port = htons(IPPORT_TELNET);
+ memset(&address.sin_addr, 0, sizeof(address.sin_addr));
+ addrLength = sizeof(address);
+
+ /* Let the kernel reuse the socket address. This lets us run
+ twice in a row, without waiting for the (ip, port) tuple
+ to time out. Makes testing much easier*/
+ conn = 1;
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &conn, sizeof(conn));
+
+ bind(sock, (struct sockaddr *) &address, sizeof(address));
+ listen(sock, 5);
+
+ printf("Waiting for telnet connection on port 23...");
+
+ if ((conn = accept(sock, (struct sockaddr *) &address,
+ &addrLength)) < 0) {
+ logMessage("accept: %s", strerror(errno));
+ exit(0);
+ return -1;
+ }
+
+ printf(" got a connection.\n");
+
+ close(sock);
+
+ telnet_negotiate(conn);
+ child = forkpty(&masterFd, NULL, NULL, NULL);
+
+ if (child < 0) {
+ logMessage("forkpty: %s", strerror(errno));
+ close(conn);
+ return -1;
+ } else if (child) {
+ fds[0].events = POLLIN;
+ fds[0].fd = masterFd;
+
+ fds[1].events = POLLIN;
+ fds[1].fd = conn;
+
+ fds[2].events = POLLIN;
+ fds[2].fd = STDIN_FILENO;
+
+ tcgetattr(STDIN_FILENO, &orig);
+ tcgetattr(STDIN_FILENO, &new);
+ new.c_lflag &= ~(ICANON | ECHO | ECHOCTL | ECHONL);
+ new.c_oflag &= ~ONLCR;
+ new.c_iflag &= ~ICRNL;
+ new.c_cc[VSUSP] = 0;
+ tcsetattr(STDIN_FILENO, 0, &new);
+
+ while ((i = poll(fds, 3, -1)) > 0) {
+ if (fds[0].revents) {
+ i = read(masterFd, buf, sizeof(buf));
+
+ /* child died */
+ if (i < 0)
+ break;
+
+ telnet_send_output(conn, buf, i);
+ write(STDOUT_FILENO, buf, i);
+ }
+
+ if (fds[1].revents) {
+ i = read(conn, buf, sizeof(buf));
+
+ /* connection went away */
+ if (!i)
+ break;
+
+ i = telnet_process_input(&ts, buf, i);
+ write(masterFd, buf, i);
+ }
+
+ if (fds[2].revents) {
+ i = read(STDIN_FILENO, buf, sizeof(buf));
+ write(masterFd, buf, i);
+ }
+ }
+
+ printf("out of poll %d\n", i);
+
+ if (i < 0) {
+ logMessage("poll: %s", strerror(errno));
+ }
+
+ kill(child, SIGTERM);
+ close(conn);
+ tcsetattr(STDIN_FILENO, 0, &orig);
+
+ exit(0);
+ }
+
+ return 0;
+}
diff --git a/loader/urls.c b/loader/urls.c
index cdf3f6517..42d912182 100644
--- a/loader/urls.c
+++ b/loader/urls.c
@@ -328,13 +328,13 @@ int urlSecondarySetupPanel(struct iurlinfo * ui, urlprotocol protocol) {
if (protocol == URL_METHOD_FTP) {
accountEntry = newtEntry(-1, -1, NULL, 24, &account,
- NEWT_ENTRY_SCROLL);
+ NEWT_FLAG_SCROLL);
passwordEntry = newtEntry(-1, -1, NULL, 24, &password,
- NEWT_ENTRY_SCROLL | NEWT_ENTRY_HIDDEN);
+ NEWT_FLAG_SCROLL | NEWT_FLAG_PASSWORD);
}
proxyEntry = newtEntry(-1, -1, ui->proxy, 24, &proxy, NEWT_ENTRY_SCROLL);
proxyPortEntry = newtEntry(-1, -1, ui->proxyPort, 6, &proxyPort,
- NEWT_ENTRY_SCROLL);
+ NEWT_FLAG_SCROLL);
entryGrid = newtCreateGrid(2, 4);
if (protocol == URL_METHOD_FTP) {