diff options
author | Erik Troan <ewt@redhat.com> | 2001-06-20 01:53:47 +0000 |
---|---|---|
committer | Erik Troan <ewt@redhat.com> | 2001-06-20 01:53:47 +0000 |
commit | b3cbb577dbe4ecda19f50f9b297b9c3e23a7a951 (patch) | |
tree | 689b6e27ac9fc7b6b1c3209ca60c8fae4190e85f /loader | |
parent | 0dd8714cdfddff257b075afb37e5001f9c81f64c (diff) | |
download | anaconda-b3cbb577dbe4ecda19f50f9b297b9c3e23a7a951.tar.gz anaconda-b3cbb577dbe4ecda19f50f9b297b9c3e23a7a951.tar.xz anaconda-b3cbb577dbe4ecda19f50f9b297b9c3e23a7a951.zip |
merge from (now defunct) anaconda-dispatch branch
added telnet server support (not turned on) along with support for cramfs'd
files in many places
Diffstat (limited to 'loader')
-rw-r--r-- | loader/Makefile | 15 | ||||
-rw-r--r-- | loader/init.c | 222 | ||||
-rw-r--r-- | loader/lang.c | 11 | ||||
-rw-r--r-- | loader/loader.c | 200 | ||||
-rw-r--r-- | loader/loader.h | 2 | ||||
-rw-r--r-- | loader/minilibc.c | 9 | ||||
-rw-r--r-- | loader/minilibc.h | 8 | ||||
-rw-r--r-- | loader/misc.c | 29 | ||||
-rw-r--r-- | loader/misc.h | 1 | ||||
-rw-r--r-- | loader/stubs.c | 15 | ||||
-rw-r--r-- | loader/telnet.c | 193 | ||||
-rw-r--r-- | loader/telnet.h | 39 | ||||
-rw-r--r-- | loader/telnetd.c | 132 | ||||
-rw-r--r-- | loader/urls.c | 6 |
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) { |