📄 loader.c~
字号:
/* * loader.c * * This is the installer loader. Its job is to somehow load the rest * of the installer into memory and run it. This may require setting * up some devices and networking, etc. The main point of this code is * to stay SMALL! Remember that, live by that, and learn to like it. * * Erik Troan <ewt@redhat.com> * Matt Wilson <msw@redhat.com> * Michael Fulbright <msf@redhat.com> * Jeremy Katz <katzj@redhat.com> * * Copyright 1997 - 2006 Red Hat, Inc. * * This software may be freely redistributed under the terms of the GNU * General Public License. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */#include <ctype.h>#include <errno.h>#include <execinfo.h>#include <fcntl.h>#include <newt.h>#include <popt.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <strings.h>#include <syslog.h>#include <unistd.h>#ifdef NASH_FIRMWARE_LOADER#include <nash.h>#endif#include <sys/ioctl.h>#include <sys/types.h>#include <sys/stat.h>#include <sys/wait.h>#include <linux/fb.h>#include <linux/serial.h>#include <linux/vt.h>#ifdef USE_MTRACE#include <mcheck.h>#endif#include "loader.h"#include "loadermisc.h" /* JKFIXME: functions here should be split out */#include "log.h"#include "lang.h"#include "kbd.h"#include "kickstart.h"#include "windows.h"/* module stuff */#include "modules.h"#include "moduleinfo.h"#include "moduledeps.h"#include "modstubs.h"#include "driverdisk.h"/* hardware stuff */#include "hardware.h"#include "firewire.h"#include "pcmcia.h"#include "usb.h"/* install method stuff */#include "method.h"#include "cdinstall.h"#include "nfsinstall.h"#include "hdinstall.h"#include "urlinstall.h"#include "net.h"#include "telnetd.h"#include <selinux/selinux.h>#include "selinux.h"#include "../isys/imount.h"#include "../isys/isys.h"#include "../isys/stubs.h"#include "../isys/lang.h"#include "../isys/eddsupport.h"#include "../isys/str.h"/* maximum number of extra arguments that can be passed to the second stage */#define MAX_EXTRA_ARGS 128static char * extraArgs[MAX_EXTRA_ARGS];static int hasGraphicalOverride();static int newtRunning = 0;/* boot flags -- we need these in a lot of places */int flags = LOADER_FLAGS_SELINUX | LOADER_FLAGS_NOFB;#ifdef INCLUDE_LOCAL#include "cdinstall.h"#include "hdinstall.h"#endif#ifdef INCLUDE_NETWORK#include "nfsinstall.h"#include "urlinstall.h"#endifint num_link_checks = 5;static struct installMethod installMethods[] = {#if !defined(__s390__) && !defined(__s390x__) { N_("Local CDROM"), "cdrom", 0, CLASS_CDROM, mountCdromImage },#endif { N_("Hard drive"), "hd", 0, CLASS_HD, mountHardDrive }, { N_("NFS directory"), "nfs", 1, CLASS_NETWORK, mountNfsImage }, { "FTP", "ftp", 1, CLASS_NETWORK, mountUrlImage }, { "HTTP", "http", 1, CLASS_NETWORK, mountUrlImage },};static int numMethods = sizeof(installMethods) / sizeof(struct installMethod);void setupRamfs(void) { mkdirChain("/tmp/ramfs"); doPwMount("none", "/tmp/ramfs", "ramfs", 0, NULL);}void doSuspend(void) { newtFinished(); exit(1);}void doShell(void) { /* this lets us debug the loader just by having a second initramfs * containing /sbin/busybox */ int child, status; newtSuspend(); if (!(child = fork())) { execl("/sbin/busybox", "msh", NULL); _exit(1); } waitpid(child, &status, 0); newtResume();}void startNewt(void) { if (!newtRunning) { char *buf = sdupprintf(_("Welcome to %s"), getProductName()); newtInit(); newtCls(); newtDrawRootText(0, 0, buf); free(buf); newtPushHelpLine(_(" <Tab>/<Alt-Tab> between elements | <Space> selects | <F12> next screen ")); newtRunning = 1; if (FL_TESTING(flags)) newtSetSuspendCallback((void *) doSuspend, NULL); else if (!access("/sbin/busybox", X_OK)) newtSetSuspendCallback((void *) doShell, NULL); }}void stopNewt(void) { if (newtRunning) newtFinished(); newtRunning = 0;}static char * productName = NULL;static char * productPath = NULL;static void initProductInfo(void) { FILE *f; int i; f = fopen("/.buildstamp", "r"); if (!f) { productName = strdup("anaconda"); productPath = strdup("anaconda"); } else { productName = malloc(256); productPath = malloc(256); productName = fgets(productName, 256, f); /* stamp time */ productName = fgets(productName, 256, f); /* product name */ productPath = fgets(productPath, 256, f); /* product version */ productPath = fgets(productPath, 256, f); /* product path */ i = strlen(productName) - 1; while (isspace(*(productName + i))) { *(productName + i) = '\0'; i--; } i = strlen(productPath) - 1; while (isspace(*(productPath + i))) { *(productPath + i) = '\0'; i--; } }}char * getProductName(void) { if (!productName) { initProductInfo(); } return productName;}char * getProductPath(void) { if (!productPath) { initProductInfo(); } return productPath;}void initializeConsole(moduleList modLoaded, moduleDeps modDeps, moduleInfoSet modInfo) { if (!FL_NOFB(flags)) mlLoadModuleSet("vgastate:vga16fb", modLoaded, modDeps, modInfo); /* enable UTF-8 console */ printf("\033%%G"); fflush(stdout); isysLoadFont(); if (!FL_TESTING(flags)) isysSetUnicodeKeymap();}/* fbcon is buggy and resets our color palette if we allocate a terminal * after initializing it, so we initialize 9 of them before we need them. * If it doesn't work, the user gets to suffer through having an ugly palette, * but things are still usable. */static void initializeTtys(void) { int fd, n; char dev[] = "/dev/ttyX"; for (n = 9; n > 0; n--) { sprintf(dev, "/dev/tty%d", n); mknod(dev, 0600, S_IFCHR | makedev(4, n)); fd = open(dev, O_RDWR|O_NOCTTY); if (fd >= 0) { ioctl(fd, VT_ACTIVATE, n); if (n == 1) ioctl(fd, VT_WAITACTIVE, n); close(fd); } else logMessage(ERROR, "failed to initialize %s", dev); }}static void spawnShell(void) { pid_t pid; if (FL_SERIAL(flags) || FL_NOSHELL(flags)) { logMessage(INFO, "not spawning a shell"); return; } else if (access("/bin/sh", X_OK)) { logMessage(ERROR, "cannot open shell - /bin/sh doesn't exist"); return; } if (!(pid = fork())) { int fd; fd = open("/dev/tty2", O_RDWR|O_NOCTTY); if (fd < 0) { logMessage(ERROR, "cannot open /dev/tty2 -- no shell will be provided"); return; } dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); close(fd); setsid(); /* enable UTF-8 console */ printf("\033%%G"); fflush(stdout); isysLoadFont(); if (ioctl(0, TIOCSCTTY, NULL)) { logMessage(ERROR, "could not set new controlling tty"); } signal(SIGINT, SIG_DFL); signal(SIGTSTP, SIG_DFL); if (!access("/mnt/source/RHupdates/pyrc.py", R_OK|X_OK)) setenv("PYTHONSTARTUP", "/mnt/source/RHupdates/pyrc.py", 1); else if (!access("/tmp/updates/pyrc.py", R_OK|X_OK)) setenv("PYTHONSTARTUP", "/tmp/updates/pyrc.py", 1); else if (!access("/usr/lib/anaconda-runtime/pyrc.py", R_OK|X_OK)) setenv("PYTHONSTARTUP", "/usr/lib/anaconda-runtime/pyrc.py", 1); setenv("LD_LIBRARY_PATH", LIBPATH, 1); setenv("LANG", "C", 1); if (execl("/bin/sh", "-/bin/sh", NULL) == -1) { logMessage(CRITICAL, "exec of /bin/sh failed: %s", strerror(errno)); exit(1); } } return;}void loadUpdates(struct loaderData_s *loaderData) { int done = 0; int rc; char * device = NULL, ** devNames = NULL; char * buf; int num = 0; do { rc = getRemovableDevices(&devNames); if (rc == 0) return; /* we don't need to ask which to use if they only have one */ if (rc == 1) { device = strdup(devNames[0]); free(devNames); } else { startNewt(); rc = newtWinMenu(_("Update Disk Source"), _("You have multiple devices which could serve " "as sources for an update disk. Which would " "you like to use?"), 40, 10, 10, rc < 6 ? rc : 6, devNames, &num, _("OK"), _("Back"), NULL); if (rc == 2) { free(devNames); return; } loaderData->updatessrc = strdup(devNames[num]); free(devNames); } buf = sdupprintf(_("Insert your updates disk into /dev/%s and press " "\"OK\" to continue."), loaderData->updatessrc); rc = newtWinChoice(_("Updates Disk"), _("OK"), _("Cancel"), buf); if (rc == 2) return; logMessage(INFO, "UPDATES device is %s", loaderData->updatessrc); devMakeInode(loaderData->updatessrc, "/tmp/upd.disk"); if (doPwMount("/tmp/upd.disk", "/tmp/update-disk", "ext2", IMOUNT_RDONLY, NULL) && doPwMount("/tmp/upd.disk", "/tmp/update-disk", "iso9660", IMOUNT_RDONLY, NULL)) { newtWinMessage(_("Error"), _("OK"), _("Failed to mount updates disk")); } else { /* Copy everything to /tmp/updates so we can unmount the disk */ winStatus(40, 3, _("Updates"), _("Reading anaconda updates...")); if (!copyDirectory("/tmp/update-disk", "/tmp/updates")) done = 1; newtPopWindow(); umount("/tmp/update-disk"); } } while (!done); return;}static int loadUpdatesFromRemote(char * url, struct loaderData_s * loaderData) { int rc = getFileFromUrl(url, "/tmp/updates.img", loaderData); if (rc != 0) return rc; copyUpdatesImg("/tmp/updates.img"); unlink("/tmp/updates.img"); return 0;}static void checkForHardDrives(void) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -