#include <alloca.h>
#include <ctype.h>
#include <fcntl.h>
#include <newt.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#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"
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 modDeps, int flags, char * mntPoint) {
char * files[] = { "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(&modDeps, from);
diskNum++;
return 0;
}
int devLoadDriverDisk(moduleInfoSet modInfo, moduleList modLoaded,
moduleDeps modDeps, 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, modDeps, NULL, flags);
devMakeInode("fd0", "/tmp/fd0");
if (doPwMount("/tmp/fd0", "/tmp/drivers", "vfat", 1, 0, NULL, NULL))
newtWinMessage(_("Error"), _("OK"),
_("Failed to mount floppy disk."));
if (devCopyDriverDisk(modInfo, modLoaded, modDeps,
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;
}
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;
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 < modInfo->numModules; i++) {
if (modInfo->moduleList[i].major == type &&
!mlModuleInList(modInfo->moduleList[i].moduleName, modLoaded)) {
newtListboxAppendEntry(listbox,
modInfo->moduleList[i].description,
(void *) i);
if (modp && (modInfo->moduleList + i) == *modp)
newtListboxSetCurrentByKey(listbox, (void *) i);
}
}
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,
FL_TESTING(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;
}