#include #include #include #include #include #include #include #include #include #include #include #include "dns.h" #include "fs.h" #include "hd.h" #include "intl.h" #include "install.h" #include "kickstart.h" #include "log.h" #include "methods.h" #include "net.h" #include "windows.h" #include "urlmethod.h" #include "scsi.h" #include "smb.h" /* This was split into two pieces to keep the initial install program small */ static void makeInstimageSymlinks(void); static int cdromPrepare(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int forceSupp, struct driversLoaded ** dl); static int hdPrepare(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int useSupp, struct driversLoaded ** dl); #ifndef DISABLE_NETWORK static int nfsPrepare(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int forceSupp, struct driversLoaded ** dl); static int urlPrepare(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int forceSupp, struct driversLoaded ** dl); #if 0 /* disable for now */ static int smbPrepare(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int useSupp, struct driversLoaded ** dl); #endif /* disable */ static int nfsGetSetup(char ** hostptr, char ** dirptr); #endif int floppyRoot(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int forceSupp, struct driversLoaded ** dl); #if 0 /* disabled */ static int totalMemory(void); /* in K */ #endif #ifndef DISABLE_NETWORK #define CDROM_METHOD_NUM 0 #define NFS_METHOD_NUM 1 #define HD_METHOD_NUM 2 #define FTP_METHOD_NUM 3 #else #define CDROM_METHOD_NUM 0 #define HD_METHOD_NUM 1 #endif /* We have a loop a bit later which translates the 'Local CDROM' language */ static struct installMethod methods[] = { { "Local CDROM", "cdrom", 0, LOCAL, cdromPrepare, NULL, NULL, NULL, NULL, NULL }, #ifndef DISABLE_NETWORK { "NFS image", "nfs", 0, NETWORK, nfsPrepare, NULL, NULL, NULL, NULL, NULL }, #endif { "Hard drive", "hd", 0, LOCAL, hdPrepare, NULL, NULL, NULL, NULL, NULL }, #ifndef DISABLE_NETWORK { "FTP", "ftp", 0, NETWORK, urlPrepare, NULL, NULL, NULL, NULL, NULL }, { "HTTP", "http", 0, NETWORK, urlPrepare, NULL, NULL, NULL, NULL, NULL }, #endif #if 0 #ifdef __i386__ { "SMB image", "smb", 0, NETWORK, smbPrepare, NULL, NULL, NULL, NULL, NULL }, #endif #endif } ; static int numMethods = sizeof(methods) / sizeof(struct installMethod); static int isMounted = 0; static void setConfig(char *first, char *firstData, ...) { char *env, *data; va_list ap; if (first && *first && firstData && *firstData) setenv(first, firstData, 1); va_start(ap, firstData); while ((env = va_arg(ap, char *))) { data = va_arg(ap, char *); if (data && *data) setenv(env, data, 1); } } #if 0 /* not currently used */ static int totalMemory(void) { int fd; int bytesRead; char buf[4096]; char * chptr, * start; int total = 0; fd = open("/proc/meminfo", O_RDONLY); if (fd < 0) { logMessage("failed to open /proc/meminfo: %s", strerror(errno)); return 0; } bytesRead = read(fd, buf, sizeof(buf) - 1); if (bytesRead < 0) { logMessage("failed to read from /proc/meminfo: %s", strerror(errno)); close(fd); return 0; } close(fd); buf[bytesRead] = '\0'; chptr = buf; while (*chptr && !total) { if (*chptr != '\n' || strncmp(chptr + 1, "MemTotal:", 9)) { chptr++; continue; } start = ++chptr ; while (*chptr && *chptr != '\n') chptr++; *chptr = '\0'; logMessage("found total memory tag: \"%s\"", start); while (!isdigit(*start) && *start) start++; if (!*start) { logMessage("no number appears after MemTotal tag"); return 0; } chptr = start; while (*chptr && isdigit(*chptr)) { total = (total * 10) + (*chptr - '0'); chptr++; } } logMessage("%d kB are available", total); return total; } #endif /* not currently used */ static int installMethodWindow(struct installMethod ** method, int showSuppBox, int isLocal, int isNetwork, int * forceSuppPtr) { int i, usedMethods = 0; newtComponent textbox, listbox, form, okay, back, result; newtGrid buttonBar, grid, middle; char forceSupp = showSuppBox ? '*' : ' '; textbox = newtTextboxReflowed(-1, -1, _("What type of media contains " "the packages to be installed?"), 30, 10, 0, 0); for (i = 0; i < numMethods; i++) { if ((isLocal && methods[i].type == LOCAL) || (isNetwork && methods[i].type == NETWORK)) usedMethods++; } listbox = newtListbox(-1, -1, usedMethods, NEWT_FLAG_RETURNEXIT); for (i = 0; i < numMethods; i++) { if ((isLocal && methods[i].type == LOCAL) || (isNetwork && methods[i].type == NETWORK)) newtListboxAddEntry(listbox, _(methods[i].name), methods + i); } buttonBar = newtButtonBar(_("Ok"), &okay, _("Back"), &back, NULL); middle = newtCreateGrid(1, 2); newtGridSetField(middle, 0, 0, NEWT_GRID_COMPONENT, listbox, 0, 0, 0, 0, 0, 0); #ifdef __i386__ if (expert || showSuppBox) newtGridSetField(middle, 0, 1, NEWT_GRID_COMPONENT, newtCheckbox(-1, -1, _("Force supplemental disk"), forceSupp, NULL, &forceSupp), 0, 1, 0, 0, NEWT_ANCHOR_LEFT, 0); #endif grid = newtGridBasicWindow(textbox, middle, buttonBar); newtGridWrappedWindow(grid, _("Installation Method")); form = newtForm(NULL, 0, 0); newtGridAddComponentsToForm(grid, form, 1); newtGridFree(grid, 1); result = newtRunForm(form); newtPopWindow(); if (result == back) { newtFormDestroy(form); return INST_CANCEL; } *method = newtListboxGetCurrent(listbox); newtFormDestroy(form); *forceSuppPtr = (forceSupp != ' '); return 0; } int chooseInstallMethod(int showSuppBox, int isLocal, int isNetwork, struct installMethod ** method, struct netInfo * netc, struct intfInfo * intf, struct driversLoaded ** dl) { int rc; int forceSupp = 0; if (kickstart) { if (!ksGetCommand(KS_CMD_CDROM, NULL, NULL, NULL)) { *method = methods + CDROM_METHOD_NUM; return (*method)->prepareImage((*method), netc, intf, 0, dl); } else if (!ksGetCommand(KS_CMD_HD, NULL, NULL, NULL)) { *method = methods + HD_METHOD_NUM; return (*method)->prepareImage((*method), netc, intf, 0, dl); #ifndef DISABLE_NETWORK } else if (!ksGetCommand(KS_CMD_NFS, NULL, NULL, NULL)) { *method = methods + NFS_METHOD_NUM; return (*method)->prepareImage((*method), netc, intf, 0, dl); } else if (!ksGetCommand(KS_CMD_URL, NULL, NULL, NULL)) { *method = methods + FTP_METHOD_NUM; return (*method)->prepareImage((*method), netc, intf, 0, dl); #endif } else { logMessage("No kickstart method was specified."); kickstart = 0; } } do { rc = installMethodWindow(method, showSuppBox, isLocal, isNetwork, &forceSupp); if (rc) return rc; if ((*method)->prepareImage) { rc = (*method)->prepareImage((*method), netc, intf, forceSupp, dl); if (rc == INST_ERROR) return rc; } } while (rc); return 0; } #ifndef DISABLE_NETWORK /* We could use newtWinEntries() here, if we didn't like those clever callbacks */ static int nfsGetSetup(char ** hostptr, char ** dirptr) { newtComponent form, okay, cancel, answer, text; newtComponent siteLabel, dirLabel; newtGrid buttons, entryArea, grid; struct nfsMountCallbackInfo cbInfo; char * reflowedText; int width, height; if (*hostptr) { cbInfo.serverVal = *hostptr; cbInfo.netpathVal = *dirptr; } else { cbInfo.serverVal = ""; cbInfo.netpathVal = ""; } form = newtForm(NULL, NULL, 0); buttons = newtButtonBar(_("Ok"), &okay, _("Back"), &cancel, NULL); reflowedText = newtReflowText( _("Please enter the following information:\n" "\n" " o the name or IP number of your NFS server\n" " o the directory on that server containing\n" " Red Hat Linux for your architecture"), 60, 10, 10, &width, &height); text = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, reflowedText); free(reflowedText); entryArea = newtCreateGrid(2, 2); siteLabel = newtLabel(-1, -1, _("NFS server name:")); newtGridSetField(entryArea, 0, 0, NEWT_GRID_COMPONENT, siteLabel, 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); dirLabel = newtLabel(-1, -1, _("Red Hat directory:")); newtGridSetField(entryArea, 0, 1, NEWT_GRID_COMPONENT, dirLabel, 0, 0, 0, 0, NEWT_ANCHOR_LEFT, 0); cbInfo.server = newtEntry(-1, -1, cbInfo.serverVal, 24, &cbInfo.serverVal, NEWT_ENTRY_SCROLL); newtComponentAddCallback(cbInfo.server, nfsMountCallback, &cbInfo); cbInfo.netpath = newtEntry(-1, -1, cbInfo.netpathVal, 24, &cbInfo.netpathVal, NEWT_ENTRY_SCROLL); cbInfo.mntpoint = NULL; newtGridSetField(entryArea, 1, 0, NEWT_GRID_COMPONENT, cbInfo.server, 1, 0, 0, 0, 0, 0); newtGridSetField(entryArea, 1, 1, NEWT_GRID_COMPONENT, cbInfo.netpath, 1, 0, 0, 0, 0, 0); grid = newtCreateGrid(1, 3); newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text, 0, 0, 0, 0, 0, 0); newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, entryArea, 0, 1, 0, 1, 0, 0); newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, buttons, 0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX); newtGridWrappedWindow(grid, _("NFS Setup")); newtGridFree(grid, 1); newtFormAddComponents(form, text, cbInfo.server, cbInfo.netpath, okay, cancel, dirLabel, siteLabel, NULL); answer = newtRunForm(form); if (answer == cancel) { newtFormDestroy(form); newtPopWindow(); return INST_CANCEL; } if (*hostptr) free(*hostptr); if (*dirptr) free(*dirptr); *hostptr = strdup(cbInfo.serverVal); *dirptr = strdup(cbInfo.netpathVal); newtFormDestroy(form); newtPopWindow(); return 0; } #endif /* ENABLE_NETWORK */ static void nukeOldModules(void) { DIR * moddir; struct dirent * ent; chdir("/modules"); moddir = opendir("/modules"); if (!moddir) return; ent = readdir(moddir); while (ent) { unlink(ent->d_name); ent = readdir(moddir); } closedir(moddir); chdir("/"); rmdir("/modules"); } /* Creates the symlinks to NFS or CD-Rom images */ static void makeInstimageSymlinks(void) { if (!access("/tmp/rhimage/RedHat/instimage/lib", X_OK)) { unlink("/tmp/rhimage/RedHat/instimage/lib"); symlink("/tmp/rhimage/RedHat/instimage/lib", "/lib"); } if (!access("/tmp/rhimage/RedHat/instimage/usr/bin", X_OK)) { unlink("/tmp/rhimage/RedHat/instimage/usr/bin"); symlink("/tmp/rhimage/RedHat/instimage/usr/bin", "/usr/bin"); } if (!access("/tmp/rhimage/RedHat/instimage/usr/etc", X_OK)) { unlink("/tmp/rhimage/RedHat/instimage/usr/etc"); symlink("/tmp/rhimage/RedHat/instimage/usr/etc", "/usr/etc"); } if (!access("/tmp/rhimage/RedHat/instimage/modules", X_OK)) { nukeOldModules(); symlink("/tmp/rhimage/RedHat/instimage/modules", "/modules"); } } static int cdromPrepare(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int useSupp, struct driversLoaded ** dl) { char * cddev; int rc = 0; if (!kickstart) rc = newtWinChoice(_("Note"), _("Ok"), ("Back"), _("Insert your Red Hat CD into your CD drive now")); if (rc == 2) return INST_CANCEL; while (1) { /* this autoprobes already, so we don't need to do anything special for the kickstart :-) */ rc = setupCDdevice(&cddev, dl); if (rc) return rc; if ((rc = loadFilesystem("isofs", "iso9660", dl))) return rc; rc = doMount(cddev, "/tmp/rhimage", "iso9660", 1, 0); if (rc) { removeCDmodule(dl); newtWinMessage(_("Error"), _("Ok"), _("I could not mount a CD on device /dev/%s"), cddev); rmdir("/tmp/rhimage"); return INST_CANCEL; } if (access("/tmp/rhimage/RedHat", R_OK)) { umount("/tmp/rhimage"); rmdir("/tmp/rhimage"); removeCDmodule(dl); newtWinMessage(_("Error"), _("Ok"), _("That CDROM device does " "not seem to contain a Red Hat CDROM.")); return INST_CANCEL; } rc = 0; while (useSupp) { rc = floppyRoot(NULL, NULL, NULL, 0, NULL); logMessage("got floppy root rc=%d", rc); if (rc == INST_CANCEL) { umount("/tmp/rhimage"); break; } else if (!rc) { logMessage("breaking out of loop"); break; } } if (!rc) break; } if (!useSupp) { makeInstimageSymlinks(); } logMessage("done here"); return 0; } #ifndef DISABLE_NETWORK static int nfsPrepare(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int useSupp, struct driversLoaded ** dl) { char * host = NULL, * dir = NULL; char * buf; enum { NFS_STEP_NET, NFS_STEP_INFO, NFS_STEP_MOUNT, NFS_STEP_DONE } step = NFS_STEP_NET; int rc; int ksArgc; char ** ksArgv; poptContext optCon; int direction = 1; struct poptOption ksNfsOptions[] = { { "server", '\0', POPT_ARG_STRING, &host, 0 }, { "dir", '\0', POPT_ARG_STRING, &dir, 0 }, { 0, 0, 0, 0, 0 } }; if (kickstart) { /* FIXME: there must be a better test to use here */ if (!intf->set || !netc->set) if (bringUpNetworking(intf, netc, dl, 1)) return INST_ERROR; ksGetCommand(KS_CMD_NFS, NULL, &ksArgc, &ksArgv); optCon = poptGetContext(NULL, ksArgc, ksArgv, ksNfsOptions, 0); if ((rc = poptGetNextOpt(optCon)) < -1) { newtWinMessage(_("nfs command"), _("Ok"), _("bad argument to kickstart nfs command %s: %s"), poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(rc)); } if (!host || !dir) { newtWinMessage(_("nfs command"), _("Ok"), _("nfs command incomplete")); } else { step = NFS_STEP_MOUNT; } } while (step != NFS_STEP_DONE) { switch (step) { case NFS_STEP_NET: rc = bringUpNetworking(intf, netc, dl, direction); if (rc) return rc; direction = 1; step = NFS_STEP_INFO; break; case NFS_STEP_INFO: if (!host && (intf->set & INTFINFO_HAS_BOOTSERVER)) host = mygethostbyaddr(inet_ntoa(intf->bootServer)); if (!dir && (intf->set & INTFINFO_HAS_BOOTFILE)) dir = strdup(intf->bootFile); rc = nfsGetSetup(&host, &dir); if (rc == INST_CANCEL) { step = NFS_STEP_NET; direction = -1; } else if (rc == INST_ERROR) return INST_ERROR; else step = NFS_STEP_MOUNT; break; case NFS_STEP_MOUNT: if (!strlen(host) || !strlen(dir)) rc = INST_ERROR; else { buf = malloc(strlen(host) + strlen(dir) + 10); strcpy(buf, host); strcat(buf, ":"); strcat(buf, dir); if ((rc = loadFilesystem("nfs", "nfs", dl))) return rc; rc = doMount(buf, "/tmp/rhimage", "nfs", 1, 0); free(buf); } if (rc) { step = NFS_STEP_INFO; newtWinMessage(_("Error"), _("Ok"), _("I could not mount that directory from the server")); } else { if (access("/tmp/rhimage/RedHat", R_OK)) { step = NFS_STEP_INFO; newtWinMessage(_("Error"), _("Ok"), _("That directory does not seem to contain " "a Red Hat installation tree.")); umount("/tmp/rhimage"); } else step = NFS_STEP_DONE; } rc = 0; while (useSupp) { rc = floppyRoot(NULL, NULL, NULL, 0, NULL); if (rc == INST_CANCEL) { umount("/tmp/rhimage"); break; } else if (!rc) { break; } } if (rc) { umount("/tmp/rhimage"); step = NFS_STEP_INFO; } break; case NFS_STEP_DONE: break; } } if (!kickstart) { free(host); free(dir); } if (!useSupp) { makeInstimageSymlinks(); } return 0; } #endif static int loadCompressedRamdisk(int fd, off_t size, char *title, char *ramdisk) { int rc = 0, ram, i; gzFile stream; char buf[1024]; newtComponent form = NULL, scale = NULL; if (testing) 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); 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(); } for (i = 0; !gzeof(stream) && !rc; i++) { if (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, sizeof(buf)) != sizeof(buf)) { logMessage("error writing to device: %s", strerror(errno)); rc = 1; } if (title != NULL && size > 0) { newtScaleSet(scale, lseek(fd, 0L, SEEK_CUR)); newtRefresh(); } } if (title != NULL) { newtPopWindow(); newtFormDestroy(form); } close(ram); gzclose(stream); return rc; } int loadStage2Ramdisk(int fd, off_t size) { int rc; rc = loadCompressedRamdisk(fd, size, _("Loading second stage ramdisk..."), "ram3"); if (rc) { errorWindow("Error loading ramdisk."); return rc; } if (doMount("ram3", "/tmp/image", "ext2", 1, 0)) { errorWindow("Error mounting ramdisk. This shouldn't " "happen, and I'm rebooting your system now."); exit(1); } symlink("/tmp/image/lib", "/lib"); symlink("/tmp/image/etc", "/etc"); symlink("/tmp/image/usr/bin", "/usr/bin"); symlink("/tmp/image/usr/etc", "/usr/etc"); symlink("/tmp/image/sbin", "/sbin"); nukeOldModules(); symlink("/tmp/image/modules", "/modules"); isMounted = 1; return 0; } int loadPCMCIADisk(void) { int rc, fd; struct stat sb; if (testing) return 0; while (doMount("fd0", "/tmp/floppy", "ext2", 1, 0) || access("/tmp/floppy/pcmcia.img", R_OK) || (fd = open("/tmp/floppy/pcmcia.img", O_RDONLY)) < 0) { umount("/tmp/floppy"); rc = newtWinChoice(_("PCMCIA Disk"), _("Ok"), _("Cancel"), _("I failed to mount the floppy. Please insert the " "Red Hat PCMCIA disk, or choose " "Cancel to pick a different installation process.")); if (rc == 2) return INST_CANCEL; } stat("/tmp/floppy/pcmcia.img", &sb); rc = loadCompressedRamdisk(fd, sb.st_size, _("Loading PCMCIA Support"), "ram2"); close(fd); umount("/tmp/floppy"); if (rc) { errorWindow("Could not load PCMCIA ramdisk"); umount("/tmp/floppy"); return INST_ERROR; } umount("/tmp/floppy"); if (doMount("ram2", "/tmp/pcmcia", "ext2", 1, 0)) { errorWindow("Error mounting ramdisk. This shouldn't " "happen, and I'm rebooting your system now."); exit(1); } symlink("/tmp/pcmcia/sbin/cardmgr", "/sbin/cardmgr"); unlink("/sbin/sh"); symlink("/tmp/pcmcia/sbin/sh", "/sbin/sh"); symlink("/tmp/pcmcia/etc/pcmcia", "/etc/pcmcia"); return 0; } int loadFloppyRoot(struct installMethod * method) { int rc, fd; struct stat sb; if (isMounted) return 0; if (testing) return 0; while (doMount("fd0", "/tmp/image", "ext2", 1, 0) || access("/tmp/image/stage2.img", R_OK) || (fd = open("/tmp/image/stage2.img", O_RDONLY)) < 0) { /* in case the mount succeeded */ umount("/tmp/image"); rc = newtWinChoice(_("Supplemental Disk"), _("Ok"), _("Cancel"), _("I failed to mount the floppy. Please insert the " "Red Hat Supplementary Install disk, or choose " "Cancel to pick a different installation process.")); if (rc == 2) return INST_CANCEL; } stat("/tmp/image/stage2.img", &sb); rc = loadCompressedRamdisk(fd, sb.st_size, _("Loading Supplemental Disk..."), "ram3"); close(fd); umount("/tmp/image"); if (doMount("ram3", "/tmp/supp", "ext2", 1, 0)) { errorWindow("Error mounting ramdisk. This shouldn't " "happen, and I'm rebooting your system now."); exit(1); } rc = newtWinChoice(_("Driver Disk"), _("Ok"), _("Back"), _("This install method requires a driver disk. Please remove " "the supplemental disk currently in your drive and replace it with " "the Red Hat Modules disk.")); if (rc == 2) return INST_CANCEL; while (doMount("fd0", "/tmp/moddisk", "ext2", 1, 0) || access("/tmp/image/modules.img", R_OK) || (fd = open("/tmp/image/modules.img", O_RDONLY)) < 0) { /* in case the mount succeeded */ umount("/tmp/image"); rc = newtWinChoice(_("Driver Disk"), _("Ok"), _("Cancel"), _("I failed to mount the floppy. Please insert the " "Red Hat Module disk, or choose " "Cancel to pick a different installation process.")); if (rc == 2) return INST_CANCEL; } stat("/tmp/floppy/modules.img", &sb); rc = loadCompressedRamdisk(fd, sb.st_size, _("Loading Driver Disk..."), "ram4"); close(fd); umount("/tmp/image"); if (doMount("ram4", "/tmp/modules", "ext2", 1, 0)) { errorWindow("Error mounting ramdisk. This shouldn't " "happen, and I'm rebooting your system now."); exit(1); } symlink("/tmp/supp/lib", "/lib"); symlink("/tmp/supp/etc", "/etc"); symlink("/tmp/supp/usr/bin", "/usr/bin"); symlink("/tmp/supp/usr/etc", "/usr/etc"); nukeOldModules(); symlink("/tmp/modules", "/modules"); isMounted = 1; return 0; } int floppyRoot(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int forceSuppDisk, struct driversLoaded ** dl) { int rc; if (!access("/usr/bin/runinstall2", R_OK)) { isMounted = 1; return 0; } do { rc = newtWinChoice(_("Supplemental Disk"), _("Ok"), _("Back"), _("This install method requires two additional disks. Please remove " "the boot disk currently in your drive and replace it with " "the Red Hat Supplementary Install disk.")); if (rc == 2) return INST_CANCEL; rc = loadFloppyRoot(method); } while (rc); return 0; } static int hdPrepare(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int useSupp, struct driversLoaded ** dl) { newtComponent okay, cancel, form, text, listbox, label, answer, dirEntry; newtGrid partGrid, buttons, entryGrid, grid; int numParts; int i; char * type; char * dir = NULL; char * partname = NULL; char * dest; char * defaultDevice; char * defaultDir; char * reflowedText; int width, height; struct partition * part = NULL; int done = 0; struct hdinfo * hdi; int rc; int fd; struct partitionTable table; int ksArgc; char ** ksArgv; poptContext optCon; struct poptOption ksHDOptions[] = { { "dir", '\0', POPT_ARG_STRING, &dir, 0 }, { "partition", '\0', POPT_ARG_STRING, &partname, 0 }, { 0, 0, 0, 0, 0 } }; setupSCSIInterfaces(0, dl, kickstart, 1); if (method->data) { hdi = method->data; defaultDir = strdup(hdi->dir); defaultDevice = hdi->device; } else { defaultDir = strdup("/"); defaultDevice = ""; } findAllPartitions(NULL, &table); if (kickstart) { ksGetCommand(KS_CMD_HD, NULL, &ksArgc, &ksArgv); optCon = poptGetContext(NULL, ksArgc, ksArgv, ksHDOptions, 0); if ((rc = poptGetNextOpt(optCon)) < -1) { newtWinMessage(_("hd command"), _("Ok"), _("bad argument to kickstart hd command %s: %s"), poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(rc)); } if (!partname || !dir) { newtWinMessage(_("hd command"), _("Ok"), _("hd command incomplete")); kickstart = 0; } else { part=0; for (i = 0; i < table.count; i++) { if (!strcmp(partname, table.parts[i].device)) { part = &table.parts[i]; break; } } /* check to see if partition was not found */ if (part == 0) { newtWinMessage(_("hd command"), _("Ok"), _("HD device %s not found"), partname); kickstart = 0; } } } while (!done) { if (!kickstart) { reflowedText = newtReflowText(_("What partition and directory on that " "partition hold the RedHat/RPMS and " "RedHat/base directories?"), 62, 5, 5, &width, &height); text = newtTextbox(-1, -1, width, height, NEWT_TEXTBOX_WRAP); newtTextboxSetText(text, reflowedText); free(reflowedText); addPartitionListbox(table, 4, PART_EXT2 | PART_DOS | PART_FAT32, NULL, &numParts, &partGrid, &listbox); buttons = newtButtonBar(_("Ok"), &okay, _("Cancel"), &cancel, NULL); for (i = 0; i < table.count; i++) { if (!strcmp(table.parts[i].device, defaultDevice)) { newtListboxSetCurrentByKey(listbox, table.parts + i); } } label = newtLabel(-1, -1, _("Directory holding Red Hat:")); dirEntry = newtEntry(28, 11, defaultDir, 28, &dir, NEWT_ENTRY_SCROLL); entryGrid = newtGridHStacked(NEWT_GRID_COMPONENT, label, NEWT_GRID_COMPONENT, dirEntry, NEWT_GRID_EMPTY); grid = newtCreateGrid(1, 4); newtGridSetField(grid, 0, 0, NEWT_GRID_COMPONENT, text, 0, 0, 0, 1, 0, 0); newtGridSetField(grid, 0, 1, NEWT_GRID_SUBGRID, partGrid, 0, 0, 0, 1, 0, 0); newtGridSetField(grid, 0, 2, NEWT_GRID_SUBGRID, entryGrid, 0, 0, 0, 1, 0, 0); newtGridSetField(grid, 0, 3, NEWT_GRID_SUBGRID, buttons, 0, 0, 0, 0, 0, NEWT_GRID_FLAG_GROWX); newtGridWrappedWindow(grid, _("Select Partition")); form = newtForm(NULL, NULL, 0); newtGridAddComponentsToForm(grid, form, 1); newtGridFree(grid, 1); answer = newtRunForm(form); if (answer != cancel) { part = newtListboxGetCurrent(listbox); } /* protect from form free */ dir = strdup(dir); newtFormDestroy(form); newtPopWindow(); if (answer == cancel) return INST_CANCEL; } /* !kickstart */ defaultDir = dir; defaultDevice = part->device; switch (part->type) { case PART_EXT2: type = "ext2"; break; case PART_DOS: type = "vfat"; break; case PART_FAT32: type = "vfat"; break; default: continue; } if (!strcmp(type, "vfat")) { if ((rc = loadFilesystem("vfat", "vfat", dl))) return rc; } if (doMount(part->device, "/tmp/hdimage", type, 1, 0)) continue; unlink("/tmp/rhimage"); /* the physical device is mounted on /tmp/hdimage, but all access are through /tmp/rhimage which points to the RedHat directory in /tmp/hdimage */ dest = alloca(strlen(dir) + 20); sprintf(dest, "/tmp/hdimage/%s", dir); if (symlink(dest, "/tmp/rhimage")) { newtWinMessage(_("Error"), _("Ok"), _("Failed to create /tmp/rhimage symlink: %s"), strerror(errno)); umount("/tmp/hdimage"); continue; } #ifdef __i386__ if (access("/tmp/rhimage/RedHat/base/stage2.img", R_OK)) { #else if (access("/tmp/rhimage/RedHat/base/hdlist", R_OK)) { #endif newtWinMessage(_("Error"), _("Ok"), _("Device %s does not appear to contain " "a Red Hat installation tree."), part->device); umount("/tmp/hdimage"); continue; } done = 1; if (method->data) { hdi = method->data; free(hdi->dir); } hdi = malloc(sizeof(*hdi)); hdi->device = part->device; hdi->type = type; hdi->dir = strdup(dir); method->data = hdi; #ifdef __i386__ if (!useSupp) { if ((fd = open("/tmp/rhimage/RedHat/base/stage2.img", O_RDONLY)) < 0) { newtWinMessage(_("Error"), _("Ok"), _("Error reading second stage ramdisk. ")); return 1; } rc = loadStage2Ramdisk(fd, 0); close(fd); if (rc) { logMessage("ramdisk load failed.\n"); return INST_ERROR; } } #endif setConfig("DEVICE", hdi->device, "TYPE", hdi->type, "DIR", hdi->dir, NULL); umount("/tmp/hdimage"); } return 0; } #ifndef DISABLE_NETWORK static int urlPrepare(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int useSupp, struct driversLoaded ** dl) { struct iurlinfo ui; enum { URL_SETUP_NET, URL_SETUP_HOST1, URL_SETUP_HOST2, URL_SETUP_CHECK, URL_SETUP_DONE } step = URL_SETUP_NET; int rc; FD_t fd; char doMore; urlprotocol protocol = URL_METHOD_FTP; char buf[256]; int ksArgc; char ** ksArgv; poptContext optCon; char *url = NULL, *proxy = NULL, *proxyport = NULL; struct poptOption ksUrlOptions[] = { { "url", '\0', POPT_ARG_STRING, &url, 0 }, { "proxy", '\0', POPT_ARG_STRING, &proxy, 0 }, { "proxyport", '\0', POPT_ARG_STRING, &proxyport, 0 }, { 0, 0, 0, 0, 0 } }; if (!strncmp(method->abbrev, "ftp", 3)) protocol = URL_METHOD_FTP; if (!strncmp(method->abbrev, "http", 4)) protocol = URL_METHOD_HTTP; memset(&ui, 0, sizeof(ui)); if (method->data) memcpy(&ui, method->data, sizeof(ui)); else memset(&ui, 0, sizeof(ui)); if (kickstart) { /* FIXME: there must be a better test to use here */ if (!intf->set || !netc->set) if (bringUpNetworking(intf, netc, dl, 1)) return INST_ERROR; ksGetCommand(KS_CMD_URL, NULL, &ksArgc, &ksArgv); optCon = poptGetContext(NULL, ksArgc, ksArgv, ksUrlOptions, 0); if ((rc = poptGetNextOpt(optCon)) < -1) { newtWinMessage(_("url command"), _("Ok"), _("bad argument to kickstart url command %s: %s"), poptBadOption(optCon, POPT_BADOPTION_NOALIAS), poptStrerror(rc)); } if (!url) { newtWinMessage(_("url command"), _("Ok"), _("url command incomplete")); } else { if (ui.urlprefix) free(ui.urlprefix); ui.urlprefix = strdup(url); if (proxy) { if (ui.proxy) free(ui.proxy); ui.proxy = strdup(proxy); if (protocol == URL_METHOD_FTP) addMacro(NULL, "_ftpproxy", NULL, ui.proxy, RMIL_RPMRC); else addMacro(NULL, "_httproxy", NULL, ui.proxy, RMIL_RPMRC); } if (proxyport) { if (ui.proxyPort) free(ui.proxyPort); ui.proxyPort = strdup(proxyport); if (protocol == URL_METHOD_FTP) addMacro(NULL, "_ftpproxyport", NULL, ui.proxyPort, RMIL_RPMRC); else addMacro(NULL, "_httpproxyport", NULL, ui.proxyPort, RMIL_RPMRC); } step = URL_SETUP_CHECK; } } while (step != URL_SETUP_DONE) { switch (step) { case URL_SETUP_NET: rc = bringUpNetworking(intf, netc, dl, 1); if (rc) return rc; step = URL_SETUP_HOST1; break; case URL_SETUP_HOST1: rc = urlMainSetupPanel(&ui, protocol, &doMore); if (rc == INST_ERROR) return rc; else if (rc) step = URL_SETUP_NET; else if (doMore == ' ') step = URL_SETUP_CHECK; else step = URL_SETUP_HOST2; break; case URL_SETUP_HOST2: rc = urlSecondarySetupPanel(&ui, protocol); if (rc == INST_ERROR) return rc; else if (rc) step = URL_SETUP_HOST1; else step = URL_SETUP_CHECK; break; case URL_SETUP_CHECK: #ifdef __i386__ if (!useSupp) { fd = urlinstStartTransfer(&ui, "base/stage2.img"); if (fd == NULL || fdFileno(fd) < 0) { newtPopWindow(); snprintf(buf, sizeof(buf), "%s/RedHat/base/stage2.img", ui.urlprefix); newtWinMessage(method->name, _("Ok"), _("Unable to retrieve the second stage ramdisk: %s"), urlStrerror(buf)); ufdClose(fd); step = URL_SETUP_HOST1; break; } rc = loadStage2Ramdisk(fdFileno(fd), 0); urlinstFinishTransfer(fd); if (rc) { logMessage("ramdisk load failed.\n"); step = URL_SETUP_HOST1; break; } } #endif setConfig("HOST", ui.address, "PREFIX", ui.prefix, "URLPREFIX", ui.urlprefix, "LOGIN", ui.login, "PASSWORD", ui.password, "PROXY", ui.proxy, "PROXYPORT", ui.proxyPort, NULL); step = URL_SETUP_DONE; break; case URL_SETUP_DONE: break; } } if (method->data) free(method->data); method->data = malloc(sizeof(ui)); memcpy(method->data, &ui, sizeof(ui)); return 0; } #endif #if 0 /* Disabled until we can get the new smb interface to the kernel right */ #ifdef __i386__ static int smbPrepare(struct installMethod * method, struct netInfo * netc, struct intfInfo * intf, int useSupp, struct driversLoaded ** dl) { char * host = NULL, * dir = NULL, * acct = NULL, * pass = NULL; char * buf; static int moduleLoaded = 0; enum { SMB_STEP_NET, SMB_STEP_INFO, SMB_STEP_MOUNT, SMB_STEP_RAM, SMB_STEP_DONE } step = SMB_STEP_NET; int rc, fd; struct stat sb; while (step != SMB_STEP_DONE) { switch (step) { case SMB_STEP_NET: rc = bringUpNetworking(intf, netc, dl, 1); if (rc) return rc; step = SMB_STEP_INFO; break; case SMB_STEP_INFO: rc = smbGetSetup(&host, &dir, &acct, &pass); if (rc == INST_CANCEL) step = SMB_STEP_NET; else if (rc == INST_ERROR) return INST_ERROR; else step = SMB_STEP_MOUNT; break; case SMB_STEP_MOUNT: if (!strlen(host) || !strlen(dir)) rc = INST_ERROR; else { buf = malloc(strlen(host) + strlen(dir) + 10); strcpy(buf, host); strcat(buf, ":"); strcat(buf, dir); if (!moduleLoaded) { rc = loadModule("smbfs", DRIVER_FS, DRIVER_MINOR_NONE, dl); if (rc) return rc; moduleLoaded = 1; } rc = doPwMount(buf, "/tmp/rhimage", "smb", 1, 0, acct, pass); free(buf); } if (rc) { step = SMB_STEP_INFO; newtWinMessage("Error", "Ok", "I could not mount that directory from the server"); } else { if (access("/tmp/rhimage/RedHat", R_OK)) { step = SMB_STEP_INFO; newtWinMessage(_("Error"), _("Ok"), _("That directory does not seem " "to contain a Red Hat installation tree.")); umount("/tmp/rhimage"); } else step = SMB_STEP_RAM; } break; case SMB_STEP_RAM: if ((fd = open("/tmp/rhimage/RedHat/base/stage2.img", O_RDONLY)) < 0) { newtWinMessage(_("Error"), _("Ok"), _("Error reading second stage ramdisk. ")); return 1; } stat("/tmp/rhimage/RedHat/base/stage2.img", &sb); rc = loadStage2Ramdisk(fd, sb.st_size); close(fd); if (rc) { logMessage("ramdisk load failed.\n"); return INST_ERROR; } case SMB_STEP_DONE: break; } } setConfig("HOST", host, "DIR", dir, "ACCT", acct, "PASS", pass, NULL); free(host); free(dir); return 0; } #endif #endif /* DISABLE */