#include #include #include #include #include #include #include #include #include "devices.h" #include "isys/imount.h" #include "../isys/isys.h" #include "lang.h" #include "loader.h" #include "misc.h" #include "modules.h" #include "windows.h" #include "../kudzu/kudzu.h" static int getModuleArgs(struct moduleInfo * mod, char *** argPtr) { struct newtWinEntry * entries; int i; int numArgs; char ** values; char * chptr, * end; int misc = -1; char ** args; int argc; int rc; char * text; entries = alloca(sizeof(*entries) * (mod->numArgs + 2)); values = alloca(sizeof(*values) * (mod->numArgs + 2)); for (i = 0; i < mod->numArgs; i++) { entries[i].text = mod->args[i].description; if (mod->args[i].arg) { values[i] = malloc(strlen(mod->args[i].arg) + 2); strcpy(values[i], mod->args[i].arg); strcat(values[i], "="); } else { values[i] = NULL; } entries[i].value = values + i; entries[i].flags = NEWT_FLAG_SCROLL; } numArgs = i; if (!(mod->flags & MI_FLAG_NOMISCARGS)) { values[i] = NULL; entries[i].text = _("Miscellaneous"); entries[i].value = values + i; entries[i].flags = NEWT_FLAG_SCROLL; misc = i; i++; } entries[i].text = (void *) entries[i].value = NULL; text = _("This module can take parameters which affects its " "operation. If you don't know what parameters to supply, " "just skip this screen by pressing the \"OK\" button " "now."); rc = newtWinEntries(_("Module Parameters"), text, 40, 5, 15, 20, entries, _("OK"), _("Back"), NULL); if (rc == 2) { for (i = 0; i < numArgs; i++) if (values[i]) free(values[i]); return LOADER_BACK; } /* we keep args big enough for the args we know about, plus a NULL */ args = malloc(sizeof(*args) * (numArgs + 1)); argc = 0; for (i = 0; i < numArgs; i++) { if (values[i] && *values[i]) { chptr = values[i] + strlen(values[i]) - 1; while (isspace(*chptr)) chptr--; if (*chptr != '=') args[argc++] = values[i]; } } if (misc >= 0 && values[misc]) { chptr = values[misc]; i = 1; while (*chptr) { if (isspace(*chptr)) i++; chptr++; } args = realloc(args, sizeof(*args) * (argc + i + 1)); chptr = values[misc]; while (*chptr) { while (*chptr && isspace(*chptr)) chptr++; if (!*chptr) break; end = chptr; while (!isspace(*end) && *end) end++; args[argc] = malloc(end - chptr + 1); memcpy(args[argc], chptr, end - chptr); args[argc][end - chptr] = '\0'; argc++; chptr = end; } free(values[misc]); } args[argc] = NULL; *argPtr = args; return 0; } int devCopyDriverDisk(moduleInfoSet modInfo, moduleList modLoaded, moduleDeps *modDepsPtr, int flags, char * mntPoint) { char * files[] = { "pcitable", "modules.cgz", "modinfo", "modules.dep", NULL }; char * dirName; char ** file; int badDisk = 0; static int diskNum = 0; char from[200], to[200]; sprintf(from, "%s/rhdd-6.1", mntPoint); if (access(from, R_OK)) badDisk = 1; dirName = malloc(80); sprintf(dirName, "/tmp/DD-%d", diskNum); mkdir(dirName, 0755); for (file = files; *file; file++) { sprintf(from, "%s/%s", mntPoint, *file); sprintf(to, "%s/%s", dirName, *file); if (copyFile(from, to)) badDisk = 1; } umount("/tmp/drivers"); if (badDisk) { return 1; } sprintf(from, "%s/modinfo", dirName); isysReadModuleInfo(from, modInfo, dirName); sprintf(from, "%s/modules.dep", dirName); mlLoadDeps(modDepsPtr, from); sprintf(from, "%s/pcitable", dirName); pciReadDrivers(from); diskNum++; return 0; } int devLoadDriverDisk(moduleInfoSet modInfo, moduleList modLoaded, moduleDeps *modDepsPtr, int flags, int cancelNotBack) { int rc; int done = 0; do { rc = newtWinChoice(_("Devices"), _("OK"), cancelNotBack ? _("Cancel") : _("Back"), _("Insert your driver disk and press \"OK\" to continue.")); if (rc == 2) return LOADER_BACK; mlLoadModule("vfat", NULL, modLoaded, (*modDepsPtr), NULL, modInfo, flags); devMakeInode("fd0", "/tmp/fd0"); if (doPwMount("/tmp/fd0", "/tmp/drivers", "vfat", 1, 0, NULL, NULL)) if (doPwMount("/tmp/fd0", "/tmp/drivers", "ext2", 1, 0, NULL, NULL)) newtWinMessage(_("Error"), _("OK"), _("Failed to mount floppy disk.")); if (devCopyDriverDisk(modInfo, modLoaded, modDepsPtr, flags, "/tmp/drivers")) newtWinMessage(_("Error"), _("OK"), _("The floppy disk you inserted is not a valid driver disk " "for this release of Red Hat Linux.")); else done = 1; } while (!done); return 0; } struct sortModuleList { int index; moduleInfoSet modInfo; }; static int sortDrivers(const void * a, const void * b) { const struct sortModuleList * one = a; const struct sortModuleList * two = b; return strcmp(one->modInfo->moduleList[one->index].description, one->modInfo->moduleList[two->index].description); } static int pickModule(moduleInfoSet modInfo, enum driverMajor type, moduleList modLoaded, moduleDeps modDeps, struct moduleInfo * suggestion, struct moduleInfo ** modp, int * specifyParams, int flags) { int i; newtComponent form, text, listbox, checkbox, ok, back; newtGrid buttons, grid, subgrid; char specifyParameters = *specifyParams ? '*' : ' '; struct newtExitStruct es; struct sortModuleList * sortedOrder; int numSorted = 0; sortedOrder = alloca(sizeof(*sortedOrder) * modInfo->numModules); for (i = 0; i < modInfo->numModules; i++) { if (modInfo->moduleList[i].major == type && !mlModuleInList(modInfo->moduleList[i].moduleName, modLoaded)) { sortedOrder[numSorted].index = i; sortedOrder[numSorted++].modInfo = modInfo; } } qsort(sortedOrder, numSorted, sizeof(*sortedOrder), sortDrivers); do { if (FL_MODDISK(flags)) { text = newtTextboxReflowed(-1, -1, _("Which driver should I try?. " "If the driver you need does not appear in this list, and " "you have a separate driver disk, please press F2."), 30, 0, 10, 0); } else { text = newtTextboxReflowed(-1, -1, _("Which driver should I try?"), 20, 0, 10, 0); } listbox = newtListbox(-1, -1, 6, NEWT_FLAG_SCROLL | NEWT_FLAG_RETURNEXIT); buttons = newtButtonBar(_("OK"), &ok, _("Back"), &back, NULL); checkbox = newtCheckbox(-1, -1, _("Specify module parameters"), specifyParameters, NULL, &specifyParameters); form = newtForm(NULL, NULL, 0); if (FL_MODDISK(flags)) newtFormAddHotKey(form, NEWT_KEY_F2); for (i = 0; i < numSorted; i++) { int num = sortedOrder[i].index; newtListboxAppendEntry(listbox, modInfo->moduleList[num].description, (void *) num); if (modp && (modInfo->moduleList + num) == *modp) newtListboxSetCurrentByKey(listbox, (void *) num); } subgrid = newtGridVStacked(NEWT_GRID_COMPONENT, listbox, NEWT_GRID_COMPONENT, checkbox, NULL); grid = newtGridBasicWindow(text, subgrid, buttons); newtGridAddComponentsToForm(grid, form, 1); newtGridWrappedWindow(grid, _("Devices")); newtFormRun(form, &es); i = (int) newtListboxGetCurrent(listbox); newtGridFree(grid, 1); newtFormDestroy(form); newtPopWindow(); if (es.reason == NEWT_EXIT_COMPONENT && es.u.co == back) { return LOADER_BACK; } else if (es.reason == NEWT_EXIT_HOTKEY && es.u.key == NEWT_KEY_F2) { devLoadDriverDisk(modInfo, modLoaded, &modDeps, flags, 0); continue; } else { break; } } while (1); *specifyParams = (specifyParameters != ' '); *modp = modInfo->moduleList + i; return 0; } int devDeviceMenu(enum driverMajor type, moduleInfoSet modInfo, moduleList modLoaded, moduleDeps modDeps, int flags, char ** moduleName) { struct moduleInfo * mod = NULL; enum { S_MODULE, S_ARGS, S_DONE } stage = S_MODULE; int rc; char ** args = NULL, ** arg; int specifyArgs = 0; while (stage != S_DONE) { switch (stage) { case S_MODULE: if ((rc = pickModule(modInfo, type, modLoaded, modDeps, mod, &mod, &specifyArgs, flags))) return LOADER_BACK; stage = S_ARGS; break; case S_ARGS: if (specifyArgs) { rc = getModuleArgs(mod, &args); if (rc) { stage = S_MODULE; break; } } stage = S_DONE; break; case S_DONE: } } if (mod->major == DRIVER_SCSI) { scsiWindow(mod->moduleName); sleep(1); } rc = mlLoadModule(mod->moduleName, mod->path, modLoaded, modDeps, args, modInfo, flags); if (mod->major == DRIVER_SCSI) newtPopWindow(); if (args) { for (arg = args; *arg; arg++) free(*arg); free(args); } if (!rc && moduleName) *moduleName = mod->moduleName; return rc; }