home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 13 / CDA13.ISO / MISC / SRC / INSTALL / DEVICES.C < prev    next >
Encoding:
C/C++ Source or Header  |  1996-12-23  |  22.3 KB  |  917 lines

  1. #include <alloca.h>
  2. #include <ctype.h>
  3. #include <fcntl.h>
  4. #include <newt.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <sys/stat.h>
  8. #include <sys/sysmacros.h>
  9. #include <sys/types.h>
  10. #include <unistd.h>
  11.  
  12. #include "devices.h"
  13. #include "install.h"
  14. #include "log.h"
  15. #include "net.h"
  16. #include "perror.h"
  17. #include "run.h"
  18. #include "scsi.h"
  19. #include "windows.h"
  20.  
  21. #define MODULES_PATH "/modules/"
  22.  
  23. struct devnum {
  24.     char * name;
  25.     short major, minor;
  26. };
  27.  
  28. const static struct devnum devices[] = {
  29.     { "aztcd",        29,    0 },
  30.     { "bpcd",        41,    0 },
  31.     { "cdu31a",        15,    0 },
  32.     { "cdu535",        24,    0 },
  33.     { "cm206cd",    32,    0 },
  34.     { "fd0",         2,    0 },
  35.     { "fd1",        2,    1 },
  36.     { "gscd",        16,    0 },
  37.     { "mcd",        23,    0 },
  38.     { "mcdx",        20,    0 },
  39.     { "optcd",        17,    0 },
  40.     { "sbpcd",        25,    0 },
  41.     { "scd0",        11,    0 },
  42.     { "scd1",        11,    1 },
  43.     { "sjcd",        18,    0 },
  44. };
  45.  
  46. const int numDevices = sizeof(devices) / sizeof(struct devnum);
  47.  
  48. struct moduleOptions {
  49.     char * arg;
  50.     char * desc;
  51.     char * defaults;
  52. } ;
  53.  
  54. const struct moduleOptions neOptions[] = {
  55.    { "io", "Base IO port:", "0x300:0x280:0x320:0x340:0x360" },
  56.    { "irq", "IRQ level:", NULL },
  57.    { NULL, NULL, NULL }
  58. } ;
  59.  
  60. const struct moduleOptions de4x5Options[] = {
  61.    { "io", "Base IO port:", "0x0b" },
  62.    { NULL, NULL, NULL }
  63. } ;
  64.  
  65. const struct moduleOptions cdu31aOptions[] = {
  66.    { "cdu31a", "IO base, IRQ, PAS?:", "" },
  67.    { NULL, NULL, NULL }
  68. } ;
  69.  
  70. const struct moduleOptions cm206Options[] = {
  71.    { "cm206", "IO base, IRQ:", "" },
  72.    { NULL, NULL, NULL }
  73. } ;
  74.  
  75. const struct moduleOptions mcdOptions[] = {
  76.    { "mcd", "IO base address:", "" },
  77.    { NULL, NULL, NULL }
  78. } ;
  79.  
  80. const struct moduleOptions optcdOptions[] = {
  81.    { "optcd", "IO base address:", "" },
  82.    { NULL, NULL, NULL }
  83. } ;
  84.  
  85. const struct moduleOptions sbpcdOptions[] = {
  86.    { "sbpcd", "IO base, IRQ, label:", "" },
  87.    { NULL, NULL, NULL }
  88. } ;
  89.  
  90. #define MODULE_AUTOPROBE    (1 << 0)
  91. #define MODULE_FAKEAUTOPROBE    (1 << 1)
  92.  
  93. struct moduleInfo {
  94.     char * name;
  95.     int shouldAutoprobe;
  96.     const struct moduleOptions * options;
  97.     int flags;
  98.     char * defaultOptions;
  99. } ;
  100.  
  101. /* keep this alphabetical! */
  102. struct moduleInfo modules[] = { 
  103.     { "8390", 1, NULL, 0, NULL },
  104.     { "cdu31a", 0, cdu31aOptions, 0, NULL },
  105.     { "cm206", 0, cm206Options, 0, NULL },
  106.     { "de4x5", 1, de4x5Options, MODULE_AUTOPROBE, "io=0" },
  107.     { "ds", 1, NULL, 0, NULL },
  108.     { "i82365", 1, NULL, 0, NULL },
  109.     { "loop", 1, NULL, 0, NULL },
  110.     { "mcd", 0, mcdOptions, 0, NULL },
  111.     { "ne", 0, neOptions, MODULE_FAKEAUTOPROBE, "io=0x300" },
  112.     { "optcd", 0, optcdOptions, 0, NULL },
  113.     { "pcmcia_core", 1, NULL, 0, NULL },
  114.     { "sbpcd", 1, sbpcdOptions, 0, NULL },
  115.     { "tcic", 1, NULL, 0, NULL },
  116.     { NULL, 0, NULL, 0, NULL }                /* sentinel */
  117. } ;
  118.  
  119. struct driver {
  120.     char * name;
  121.     char * modules;
  122.     int isLoaded;
  123.     driverOkayFn okay;
  124.     enum driverTypes type;
  125. };
  126.  
  127. static int checkEthernetDev(struct driver * dev);
  128. static int checkSCSIDev(struct driver * dev);
  129.  
  130. static struct driver drivers[] = {
  131.     { "3com 3c509", "3c509", 0, checkEthernetDev, 
  132.         DRIVER_ETHERNET },
  133.     { "3com 3c59x (Vortex)", "3c59x", 0, checkEthernetDev,
  134.         DRIVER_ETHERNET },
  135.     { "3com 3c501", "3c501", 0, checkEthernetDev, 
  136.         DRIVER_ETHERNET },
  137.     { "3com 3c503", "8390:3c503", 0, checkEthernetDev, 
  138.         DRIVER_ETHERNET },
  139.     { "Apricot 82596", "apricot", 0, checkEthernetDev, 
  140.         DRIVER_ETHERNET },
  141.     { "Cabletron E2100", "8390:e2100", 0, checkEthernetDev, 
  142.         DRIVER_ETHERNET },
  143.     { "Digital 425,434,435,450,500", "de4x5", 0, checkEthernetDev, 
  144.         DRIVER_ETHERNET },
  145.     { "Digital DEPCA and EtherWORKS", "depca", 0, checkEthernetDev, 
  146.         DRIVER_ETHERNET },
  147.     { "Digital EtherWORKS 3", "ewrk3", 0, checkEthernetDev, 
  148.         DRIVER_ETHERNET },
  149.     { "Digital 21040 (Tulip)", "tulip", 0, checkEthernetDev, 
  150.         DRIVER_ETHERNET },
  151.     { "D-Link DE-600 pocket adapter", "de600", 0, checkEthernetDev, 
  152.         DRIVER_ETHERNET },
  153.     { "D-Link DE-620 pocket adapter", "de620", 0, checkEthernetDev, 
  154.         DRIVER_ETHERNET },
  155.     { "HP10/100VG any LAN ", "8390:hp", 0, checkEthernetDev, 
  156.         DRIVER_ETHERNET },
  157.     { "HP LAN", "hp", 0, checkEthernetDev, 
  158.         DRIVER_ETHERNET },
  159.     { "HP PCLAN/plus", "8390:hp-plus", 0, checkEthernetDev, 
  160.         DRIVER_ETHERNET },
  161.     { "Intel EtherExpress", "eexpress", 0, checkEthernetDev, 
  162.         DRIVER_ETHERNET },
  163.     { "NE2000 and compatible", "8390:ne", 0, checkEthernetDev, 
  164.         DRIVER_ETHERNET },
  165.     { "SMC 9000 series", "smc9194", 0, checkEthernetDev, 
  166.         DRIVER_ETHERNET },
  167.     { "SMC Ultra ethernet", "8390:smc-ultra", 0, checkEthernetDev, 
  168.         DRIVER_ETHERNET },
  169.     { "WD8003, WD8013 and compatible", "8390:wd", 0, checkEthernetDev,
  170.         DRIVER_ETHERNET },
  171.  
  172.     { "Adaptec 152x", "aha152x", 0, checkSCSIDev,
  173.         DRIVER_SCSI },
  174.     { "Adaptec 1542", "aha1542", 0, checkSCSIDev,
  175.         DRIVER_SCSI },
  176.     { "Adaptec 1740", "aha1740", 0, checkSCSIDev,
  177.         DRIVER_SCSI },
  178.     { "Adaptec 2740, 2840, 2940", "aic7xxx", 0, checkSCSIDev,
  179.         DRIVER_SCSI },
  180.     { "AdvanSys Adapters", "advansys", 0, checkSCSIDev,
  181.         DRIVER_SCSI },
  182.     { "Always IN2000", "in2000", 0, checkSCSIDev,
  183.         DRIVER_SCSI },
  184.     { "Buslogic Adapters", "BusLogic", 0, checkSCSIDev,
  185.         DRIVER_SCSI },
  186.     { "DTC 3180/3280", "dtc", 0, checkSCSIDev,
  187.         DRIVER_SCSI },
  188.     { "EATA DMA Adapters", "eata_dma", 0, checkSCSIDev,
  189.         DRIVER_SCSI },
  190.     { "EATA PIO Adapters)", "eata_pio", 0, checkSCSIDev,
  191.         DRIVER_SCSI },
  192.     { "Future Domain TMC-885, TMC-950", "seagate", 0, checkSCSIDev,
  193.         DRIVER_SCSI },
  194.     { "Future Domain TMC-16x0", "fdomain", 0, checkSCSIDev,
  195.         DRIVER_SCSI },
  196.     { "Iomega PPA3 (parallel port Zip)", "ppa", 0, checkSCSIDev,
  197.         DRIVER_SCSI },
  198.     { "NCR 5380", "g_NCR5380", 0, checkSCSIDev,
  199.         DRIVER_SCSI },
  200.     { "NCR 53c406a", "NCR53c406a", 0, checkSCSIDev,
  201.         DRIVER_SCSI },
  202.     { "NCR 53C810/53C820 PCI", "53c7,8xx", 0, checkSCSIDev,
  203.         DRIVER_SCSI },
  204.     { "NCR 53C810/53C820 (alternate)", "ncr53c8xx", 0, checkSCSIDev,
  205.         DRIVER_SCSI },
  206.     { "Pro Audio Spectrum/Studio 16", "pas16", 0, checkSCSIDev,
  207.         DRIVER_SCSI },
  208.     { "Qlogic FAS", "qlogicfas", 0, checkSCSIDev,
  209.         DRIVER_SCSI },
  210.     { "Qlogic ISP", "qlogicisp", 0, checkSCSIDev,
  211.         DRIVER_SCSI },
  212.     { "Seagate ST01/02", "seagate", 0, checkSCSIDev,
  213.         DRIVER_SCSI },
  214.     { "Trantor T128/T128F/T228", "seagate", 0, checkSCSIDev,
  215.         DRIVER_SCSI },
  216.     { "UltraStor 14F/34F", "u14-34f", 0, checkSCSIDev,
  217.         DRIVER_SCSI },
  218.     { "UltraStor 14F/24F/34F", "ultrastor", 0, checkSCSIDev,
  219.         DRIVER_SCSI },
  220.     { "Western Digital wd7000", "wd7000", 0, checkSCSIDev,
  221.         DRIVER_SCSI },
  222.  
  223.     { "PCMCIA core support", "pcmcia_core", 0, NULL,
  224.         DRIVER_PCMCIA },
  225.     { "PCMCIA card support", "ds", 0, NULL,
  226.         DRIVER_PCMCIA },
  227.     { "PCMCIA i82365 controller", "i82365", 0, NULL,
  228.         DRIVER_PCMCIA },
  229.     { "PCMCIA tcic controller", "tcic", 0, NULL,
  230.         DRIVER_PCMCIA },
  231.  
  232.     { "Aztech CD", "aztcd", 0, NULL,
  233.         DRIVER_CDROM },
  234.     { "Backpack CDROM", "bpcd", 0, NULL,
  235.         DRIVER_CDROM },
  236.     { "Goldstar R420", "gscd", 0, NULL,
  237.         DRIVER_CDROM },
  238.     { "Mitsumi", "mcd", 0, NULL,
  239.         DRIVER_CDROM },
  240.     { "Mitsumi (alternate)", "mcdx", 0, NULL,
  241.         DRIVER_CDROM },
  242.     { "Optics Storage 8000", "optcd", 0, NULL,
  243.         DRIVER_CDROM },
  244.     { "Phillips CM206/CM260", "cm206", 0, NULL,
  245.         DRIVER_CDROM },
  246.     { "Sanyo", "sjcd", 0, NULL, 
  247.         DRIVER_CDROM },
  248.     { "Sony CDU-31A", "cdu31a", 0, NULL, 
  249.         DRIVER_CDROM },
  250.     { "Sony CDU-5xx", "sonycd535", 0, NULL, 
  251.         DRIVER_CDROM },
  252.     { "SoundBlaster/Panasonic", "sbpcd", 0, NULL, 
  253.         DRIVER_CDROM },
  254.  
  255.     { "Loopback device", "loop", 0, NULL, DRIVER_OTHER },
  256.  
  257.     { NULL, NULL, 0, NULL, DRIVER_OTHER }, /* sentinel */
  258. };
  259.  
  260. static const int numDrivers = sizeof(drivers) / sizeof(struct driver);
  261.  
  262. static int loadDeviceModule(struct driver * driver, 
  263.                 struct driversLoaded ** drlist);
  264. static int getOptions(const char * name, int * argcp, char *** argvp);
  265. static struct driversLoaded * allocDL(struct driversLoaded ** drlist);
  266.  
  267. int devMakeInode(char * name, char * path) {
  268.     int i;
  269.     int major, minor;
  270.  
  271.     if (name[0] == 's' && name[1] == 'd') {
  272.     major = 8;
  273.     minor = (name[2] - 'a') << 4;
  274.     if (name[3] && name[4]) 
  275.        minor += 10 + (name[4] - '0');
  276.     else if (name[3])
  277.        minor += (name[3] - '0');
  278.     } else if (name[0] == 'h' && name[1] == 'd') {
  279.     if (name[2] == 'a') 
  280.         major = 3, minor = 0;
  281.     else if (name[2] == 'b')
  282.         major = 3, minor = 64;
  283.     else if (name[2] == 'c')
  284.         major = 22, minor = 0;
  285.     else if (name[2] == 'd')
  286.         major = 22, minor = 64;
  287.     else if (name[2] == 'e')
  288.         major = 33, minor = 0;
  289.     else if (name[2] == 'f')
  290.         major = 33, minor = 64;
  291.     else if (name[2] == 'g')
  292.         major = 34, minor = 0;
  293.     else if (name[2] == 'h')
  294.         major = 34, minor = 64;
  295.     else
  296.         return INST_ERROR;
  297.  
  298.     if (name[3] && name[4]) 
  299.        minor += 10 + (name[4] - '0');
  300.     else if (name[3])
  301.        minor += (name[3] - '0');
  302.     } else if (!strncmp(name, "ram", 3)) {
  303.     major = 1;
  304.     minor = 1;
  305.     if (name[3])
  306.         minor += name[3] - '1';
  307.     } else {
  308.     for (i = 0; i < numDevices; i++) {
  309.         if (!strcmp(devices[i].name, name)) break;
  310.     }
  311.     if (i == numDevices) return INST_ERROR;
  312.     major = devices[i].major;
  313.     minor = devices[i].minor;
  314.     }
  315.  
  316.     logMessage("making device %s (%d, %d) as %s", name, major, minor, path);
  317.  
  318.     if (testing)
  319.     messageWindow("mknod", "making device %s (%d, %d) as %s", 
  320.               name, major, minor, path);
  321.  
  322.     unlink(path);
  323.     if (mknod(path, S_IFBLK | 0600, makedev(major, minor))) {
  324.     messageWindow("Error", perrorstr("mknod() failed"));
  325.     return INST_ERROR;
  326.     }
  327.  
  328.     return 0;
  329. }
  330.  
  331. void devRemoveInode(char * path) {
  332.     logMessage("removing device file %s", path);
  333.     unlink(path);
  334. }
  335.  
  336. static int modulesPanel(enum driverTypes type, struct driver ** drvptr) {
  337.     int drCount = 0;
  338.     int i;
  339.     newtComponent label, f, listbox;
  340.     newtComponent okay, answer, cancel;
  341.  
  342.     for (i = 0; i < numDrivers; i++) {
  343.     if (drivers[i].type == type) drCount++;
  344.     }
  345.  
  346.     newtOpenWindow(17, 4, 45, 15, "Load module");
  347.  
  348.     f = newtForm(NULL, NULL, 0);
  349.     label = newtLabel(1, 1, "Which driver should I try?");
  350.     newtFormAddComponent(f, label);
  351.  
  352.     listbox = newtListbox(5, 3, 6, NEWT_LISTBOX_RETURNEXIT);
  353.  
  354.     drCount = 0;
  355.     for (i = 0; i < numDrivers; i++) {
  356.     if (drivers[i].type == type) {
  357.         newtListboxAddEntry(listbox, drivers[i].name, drivers + i);
  358.         drCount++;
  359.     }
  360.     }
  361.  
  362.     newtFormAddComponent(f, listbox);
  363.     okay = newtButton(8, 10, "Ok");
  364.     cancel = newtButton(28, 10, "Cancel");
  365.  
  366.     newtFormAddComponents(f, okay, cancel, NULL);
  367.  
  368.     answer = newtRunForm(f);
  369.  
  370.     if (answer == cancel) {
  371.     newtFormDestroy(f);
  372.     newtPopWindow();
  373.     return INST_CANCEL;
  374.     }
  375.  
  376.     *drvptr = newtListboxGetCurrent(listbox);
  377.  
  378.     newtFormDestroy(f);
  379.     newtPopWindow();
  380.  
  381.     return 0;
  382. }
  383.  
  384. int loadDeviceDriver(enum driverTypes type, struct driversLoaded ** drlist) {
  385.     struct driver * driver;
  386.     int rc;
  387.  
  388.     do {
  389.     rc = modulesPanel(type, &driver);
  390.     if (rc) return rc;
  391.  
  392.     rc = loadDeviceModule(driver, drlist);
  393.     if (rc == INST_ERROR) {
  394.         errorWindow("I can't find the device anywhere on your system!");
  395.     }
  396.     } while (rc);
  397.  
  398.     return 0;
  399. }
  400.  
  401. static int loadDeviceModule(struct driver * driver, 
  402.                 struct driversLoaded ** drlist) {
  403.     char * start, * chptr, ** modStack;
  404.     char moduleName[100];
  405.     int rc;
  406.     int nummods = 1;
  407.    
  408.     chptr = start = driver->modules;
  409.     while (*chptr) {
  410.     if (*chptr == ':') nummods++;
  411.     chptr++;
  412.     }
  413.  
  414.     modStack = alloca(sizeof(char *) * (nummods + 1));
  415.  
  416.     nummods = 0;
  417.     while (start && *start) {
  418.     chptr = strchr(start, ':');
  419.     if (chptr) {
  420.         strncpy(moduleName, start, chptr - start);
  421.         moduleName[chptr - start] = '\0';
  422.         start = chptr + 1;
  423.     } else {
  424.         strcpy(moduleName, start);
  425.         start = NULL;
  426.     }
  427.  
  428.     if ((rc = loadModule(moduleName, driver->type, drlist))) {
  429.         while (nummods) {
  430.         removeModule(modStack[--nummods]);
  431.         }
  432.         return rc;
  433.     }
  434.  
  435.     
  436.     modStack[nummods] = alloca(strlen(moduleName) + 1);
  437.     strcpy(modStack[nummods++], moduleName);
  438.     }
  439.  
  440.     if (driver->okay && !driver->okay(driver)) {
  441.     while (nummods) {
  442.         removeModule(modStack[--nummods]);
  443.     }
  444.     logMessage("device check function failed to find device");
  445.     return INST_ERROR;
  446.     }
  447.  
  448.     return 0;
  449. }
  450.  
  451. int removeModule(char * module) {
  452.     char * argv[] = { "/bin/rmmod", NULL, NULL };
  453.  
  454.     argv[1] = module;
  455.  
  456.     return runProgram(RUN_LOG, "/bin/rmmod", argv);
  457. }
  458.  
  459. int loadModule(char * modName, enum driverTypes type,
  460.            struct driversLoaded ** drlist) {
  461.     struct driversLoaded * dl;
  462.     char * objName;
  463.     char ** argv;
  464.     int argc;
  465.     int rc;
  466.     int clearWindow = 0;
  467.  
  468.     if (type == DRIVER_SCSI) {
  469.     winStatus(35, 3, "SCSI", "Scanning SCSI bus...");
  470.     clearWindow = 1;
  471.     }
  472.  
  473.     objName = alloca(strlen(modName) + 5 + strlen(MODULES_PATH));
  474.  
  475.     strcpy(objName, MODULES_PATH);
  476.     strcat(objName, modName);
  477.     strcat(objName, ".o");
  478.  
  479.     argc = 2;
  480.     argv = malloc((argc + 1) * sizeof(char *));
  481.     argv[0] = "/bin/insmod";
  482.     argv[1] = objName;
  483.     argv[2] = NULL;
  484.  
  485.     if ((rc = getOptions(modName, &argc, &argv))) {
  486.     free(argv);
  487.     if (clearWindow) newtPopWindow();
  488.     return rc;
  489.     } 
  490.  
  491.     if (runProgram(RUN_LOG, "/bin/insmod", argv)) {
  492.     free(argv);
  493.     logMessage("insmod failed!");
  494.     if (clearWindow) newtPopWindow();
  495.     return INST_ERROR;
  496.     }
  497.  
  498.     if (drlist) { 
  499.     dl = allocDL(drlist);
  500.  
  501.     dl->type = type;
  502.     dl->argv = argv;
  503.     dl->argc = argc;
  504.     dl->module = strdup(modName);
  505.     }
  506.  
  507.     if (clearWindow) newtPopWindow();
  508.  
  509.     return 0;
  510. }
  511.  
  512. static struct driversLoaded * allocDL(struct driversLoaded ** drlist) {
  513.     struct driversLoaded * new;
  514.  
  515.     if (*drlist == NULL) {
  516.     *drlist = malloc(sizeof(**drlist));
  517.     new = *drlist;
  518.     } else {
  519.     new = *drlist;
  520.     while (new->next) new = new->next;
  521.     new->next = malloc(sizeof(**drlist));
  522.     new = new->next;
  523.     }
  524.  
  525.     new->next = NULL;
  526.  
  527.     return new;
  528. }
  529.  
  530. #define OPTIONS_SPECIFY ((void *) 1)
  531. #define OPTIONS_DEFAULT ((void *) 2)
  532.  
  533. static int getOptions(const char * name, int * argcp, char *** argvp) {
  534.     newtComponent form, listbox, text, okay, answer, cancel;
  535.     char ** parameters = NULL;
  536.     char * miscParameters;
  537.     char buf[2000];
  538.     struct moduleInfo * mod;
  539.     void * choice;
  540.     int numOptions, col, miscRow, buttonRow, i;
  541.     const struct moduleOptions * option;
  542.     char * miscText;
  543.     char * chptr, * start;
  544.  
  545.     mod = modules;
  546.     while (mod->name) {
  547.     if (!strcmp(mod->name, name)) break;
  548.     mod++;
  549.     }
  550.     if (!mod->name) mod = NULL;
  551.     
  552.     if (mod && !mod->options) {
  553.     (*argcp)++;
  554.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  555.     (*argvp)[(*argcp) - 1] = mod->defaultOptions;
  556.     (*argvp)[(*argcp)] = NULL;
  557.     if (!mod->defaultOptions)
  558.         (*argcp)--;
  559.     
  560.     return 0;
  561.     }
  562.  
  563.     if (!mod || mod->shouldAutoprobe) {
  564.     sprintf(buf, "In some cases, the %s driver needs to have extra "
  565.         "information to work properly, although it normally works "
  566.         "fine without. Would you like to specify extra options "
  567.         "for it or allow the driver to probe your machine for the "
  568.         "information it needs? Occasionally, probing will hang a "
  569.         "computer, but it should not cause any damage.", name);
  570.  
  571.     newtOpenWindow(10, 4, 60, 16, "Module Options");
  572.     listbox = newtListbox(20, 9, 0, NEWT_LISTBOX_RETURNEXIT);
  573.     newtListboxAddEntry(listbox, "Autoprobe", OPTIONS_DEFAULT);
  574.     newtListboxAddEntry(listbox, "Specify options", OPTIONS_SPECIFY);
  575.     buttonRow = 12;
  576.     } else {
  577.     sprintf(buf, "In many cases, the %s driver needs to be provided with "
  578.         "extra information on your hardware. If you prefer, "
  579.         "some common values for those parameters will be tried. "
  580.         "This process can hang a machine, although it should "
  581.         "not cause any damage.", name);
  582.     newtOpenWindow(10, 5, 60, 14, "Module Options");
  583.     listbox = newtListbox(20, 7, 0, NEWT_LISTBOX_RETURNEXIT);
  584.     newtListboxAddEntry(listbox, "Specify options", OPTIONS_SPECIFY);
  585.     newtListboxAddEntry(listbox, "Autoprobe", OPTIONS_DEFAULT);
  586.     buttonRow = 10;
  587.     }
  588.  
  589.     text = newtTextbox(1, 1, 55, 7, NEWT_TEXTBOX_WRAP);
  590.     newtTextboxSetText(text, buf);
  591.  
  592.     okay = newtButton(13, buttonRow, "Ok");
  593.     cancel = newtButton(39, buttonRow, "Cancel");
  594.  
  595.     form = newtForm(NULL, NULL, 0);
  596.     newtFormAddComponents(form, text, listbox, okay, cancel, NULL);
  597.  
  598.     answer = newtRunForm(form);
  599.     newtPopWindow();
  600.  
  601.     choice = newtListboxGetCurrent(listbox);
  602.     newtFormDestroy(form);
  603.  
  604.     if (answer == cancel) {
  605.     return INST_CANCEL;
  606.     }
  607.  
  608.     if (choice == OPTIONS_DEFAULT) {
  609.     (*argcp)++;
  610.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  611.     if (mod)
  612.         (*argvp)[(*argcp) - 1] = mod->defaultOptions;
  613.     (*argvp)[(*argcp)] = NULL;
  614.     if (!mod || !mod->defaultOptions)
  615.         (*argcp)--;
  616.     
  617.     return 0;
  618.     }
  619.  
  620.     form = newtForm(NULL, NULL, 0);
  621.     newtFormAddComponent(form, newtLabel(1, 1, "Module options:"));
  622.  
  623.     numOptions = 0;
  624.     col = 0;
  625.     if (mod) {
  626.     option = mod->options;
  627.     while (option->arg) {
  628.         newtFormAddComponent(form, newtLabel(3, 3 + numOptions, 
  629.                  option->desc));
  630.         if (strlen(option->desc) > col) col = strlen(option->desc);
  631.         numOptions++;
  632.         option++;
  633.     }
  634.     miscText = "Miscellaneous options:";
  635.     } else {
  636.     miscText = "Module options:";
  637.     }
  638.  
  639.     if (numOptions) 
  640.     miscRow = 4 + numOptions; 
  641.     else
  642.     miscRow = 3;
  643.  
  644.     newtFormAddComponent(form, newtLabel(3, miscRow, "Miscellaneous options:"));
  645.  
  646.     if (22 > col) col = 22;
  647.  
  648.     if (numOptions) {
  649.     parameters = alloca(sizeof(*parameters) * numOptions);
  650.     numOptions = 0;
  651.     option = mod->options;
  652.     while (option->arg) {
  653.         sprintf(buf, "%s=", option->arg);
  654.         newtFormAddComponent(form, newtEntry(col + 5, 3 + numOptions, 
  655.                  buf, 20, parameters + numOptions, 
  656.                  NEWT_ENTRY_SCROLL));
  657.         numOptions++;
  658.         option++;
  659.     }
  660.     }
  661.  
  662.     newtFormAddComponent(form, newtEntry(col + 5, miscRow, "", 20,
  663.              &miscParameters, NEWT_ENTRY_SCROLL));
  664.  
  665.     newtOpenWindow((80 - (col + 30)) / 2, (25 - (miscRow + 6)) / 2, col + 30,
  666.             miscRow + 6, "Module Parameters");
  667.  
  668.     okay = newtButton((col + 10) / 3, miscRow + 2, "Ok");
  669.     cancel = newtButton(10 + 2 * ((col + 10) / 3), miscRow + 2, "Cancel");
  670.     newtFormAddComponents(form, okay, cancel, NULL);
  671.  
  672.     answer = newtRunForm(form);
  673.  
  674.     newtPopWindow();
  675.  
  676.     if (answer == cancel) {
  677.     newtFormDestroy(form);
  678.     return INST_CANCEL;
  679.     }
  680.  
  681.     if (mod) {
  682.     i = *argcp;
  683.     (*argcp) += numOptions;
  684.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  685.     numOptions = 0;
  686.      
  687.     option = mod->options;
  688.     while (option->arg) {
  689.         sprintf(buf, "%s=", option->arg);
  690.         if (strcmp(parameters[numOptions], buf))
  691.         (*argvp)[i++] = strdup(parameters[numOptions]);
  692.         numOptions++, option++;
  693.     }
  694.     (*argcp) = i;
  695.     }
  696.  
  697.     chptr = miscParameters;
  698.     numOptions = 0;
  699.     while (*chptr) {
  700.     while (isspace(*chptr) && *chptr) chptr++;
  701.     if (!*chptr) continue;
  702.     
  703.     numOptions++;
  704.     while (!isspace(*chptr) && *chptr) chptr++;
  705.     }
  706.  
  707.     i = *argcp;
  708.     (*argcp) += numOptions;
  709.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  710.     numOptions = 0;
  711.  
  712.     chptr = miscParameters;
  713.     numOptions = 0;
  714.     while (*chptr) {
  715.     while (isspace(*chptr) && *chptr) chptr++;
  716.     if (!*chptr) continue;
  717.     
  718.     start = chptr;
  719.     numOptions++;
  720.     while (!isspace(*chptr) && *chptr) chptr++;
  721.  
  722.     if (*chptr) {
  723.         *chptr = '\0';
  724.         (*argvp)[i++] = strdup(start);
  725.         *chptr = ' ';
  726.     } else
  727.         (*argvp)[i++] = strdup(start);
  728.     }
  729.     (*argcp) = i;
  730.     (*argvp)[*argcp] = NULL;
  731.  
  732.     newtFormDestroy(form);
  733.  
  734.     return 0;
  735. }
  736.  
  737. int readModuleConf(char * prefix, struct driversLoaded ** drlist) {
  738.     char buf[255];
  739.     FILE * f;
  740.     char * start, * end, * chptr;
  741.     struct driversLoaded * item = NULL;
  742.  
  743.     if (testing) return 0;
  744.  
  745.     strcpy(buf, prefix);
  746.     strcat(buf, "/conf.modules");
  747.  
  748.     f = fopen(buf, "r");
  749.     if (!f) {
  750.     return INST_ERROR;
  751.     }
  752.  
  753.     while (fgets(buf, sizeof(buf) - 1, f)) {
  754.      start = buf;
  755.     end = start + strlen(start) - 1;
  756.     *end = '\0';
  757.  
  758.     if (!strncmp(start, "alias ", 6)) {
  759.         start += 6;
  760.  
  761.         if (!strncmp(start, "eth", 3)) {
  762.         start += 5;
  763.  
  764.         item = allocDL(drlist);
  765.  
  766.         item->module = strdup(start);
  767.         item->argv = NULL;
  768.         item->argc = 0;
  769.         item->type = DRIVER_ETHERNET;
  770.         } else if (!strncmp(start, "scsi_hostadapter", 16)) {
  771.         start += 17;
  772.         while (isspace(*start) && *start) start++;
  773.         if (!*start) continue;
  774.  
  775.         item = allocDL(drlist);
  776.  
  777.         item->module = strdup(start);
  778.         item->argv = NULL;
  779.         item->argc = 0;
  780.         item->type = DRIVER_SCSI;
  781.         }
  782.     } else if (!strncmp(start, "options ", 8)) {
  783.         start += 8;
  784.  
  785.         chptr = start;
  786.         while (!isspace(*chptr) && *chptr) chptr++;
  787.         if (!*chptr) continue;
  788.         
  789.         *chptr = '\0';
  790.         
  791.         item = *drlist;
  792.         while (item && strcmp(item->module, start)) item = item->next; 
  793.  
  794.         if (!item) {
  795.         item = allocDL(drlist);
  796.         item->module = strdup(start);
  797.         item->argv = NULL;
  798.         item->argc = 0;
  799.         item->type = DRIVER_ETHERNET;
  800.         }
  801.  
  802.         item->argv = malloc(sizeof(char *) * 5);
  803.         item->argc = 3;
  804.         item->argv[2] = strdup(chptr + 1);
  805.     }
  806.     }
  807.  
  808.     fclose(f);
  809.  
  810.     return 0;
  811. }
  812.  
  813. int writeModuleConf(char * prefix, struct driversLoaded * dl) {
  814.     char buf[255];
  815.     char buf2[255];
  816.     FILE * f;
  817.     int i;
  818.  
  819.     if (testing) return 0;
  820.  
  821.     strcpy(buf, prefix);
  822.     strcat(buf, "/conf.modules");
  823.  
  824.     if (!access(buf, X_OK)) {
  825.     logMessage("backing up old conf.modules");
  826.     strcpy(buf2, buf);
  827.     strcat(buf2, ".orig");
  828.     rename(buf, buf2);
  829.     }
  830.  
  831.     f = fopen(buf, "w");
  832.     if (!f) {
  833.     errorWindow("cannot create module config file: %s");
  834.     return INST_ERROR;
  835.     }
  836.  
  837.     while (dl) {
  838.     if (dl->type == DRIVER_ETHERNET) {
  839.         fprintf(f, "alias eth0 %s\n", dl->module);
  840.     }
  841.     else if (dl->type == DRIVER_SCSI) {
  842.         fprintf(f, "alias scsi_hostadapter %s\n", dl->module);
  843.     }
  844.  
  845.     if (dl->argc > 2) {
  846.         fprintf(f, "options %s", dl->module);
  847.         for (i = 2; i < dl->argc; i++) {
  848.         fprintf(f, " %s", dl->argv[i]);
  849.         }
  850.     
  851.         fprintf(f, "\n");
  852.     }
  853.  
  854.     dl = dl->next;
  855.     }
  856.  
  857.     fclose(f);
  858.  
  859.     return 0;
  860. }
  861.  
  862. static int checkSCSIDev(struct driver * dev) {
  863.     return scsiDeviceAvailable();
  864. }
  865.  
  866. static int checkEthernetDev(struct driver * dev) {
  867.     return netDeviceAvailable("eth0");
  868. }
  869.  
  870. /* This assumes only one of each driver type is loaded */
  871. int removeDeviceDriver(enum driverTypes type, struct driversLoaded ** drlist) {
  872.     char * buf, * chptr;
  873.     struct driversLoaded * dl, * head;
  874.     struct driver * dri;
  875.  
  876.     dl = *drlist;
  877.     while (dl && dl->type != type) {
  878.     dl = dl->next;
  879.     }
  880.     if (!dl) return 0;
  881.  
  882.     dri = drivers;
  883.     while (dri->name) {
  884.     if (!strcmp(dri->modules, dl->module)) break;
  885.     dri++;
  886.     }
  887.  
  888.     if (!dri->name) return 0;
  889.  
  890.     buf = alloca(strlen(dri->modules) + 1);
  891.     strcpy(buf, dri->modules);
  892.  
  893.     chptr = buf + strlen(buf) - 1;
  894.     while (chptr > buf) {
  895.     while (chptr > buf && *chptr != ':') chptr--;
  896.     if (*chptr == ':') {
  897.         chptr = '\0';
  898.         removeModule(chptr + 1);
  899.         chptr--;
  900.     }
  901.     }
  902.  
  903.     removeModule(buf);
  904.  
  905.     if (dl == *drlist) {
  906.     *drlist = dl->next;
  907.     free(dl);
  908.     } else if (dl) {
  909.     head = *drlist;
  910.     while (head->next != dl) head = head->next;
  911.     head->next = dl->next;
  912.     free(dl);
  913.     }
  914.  
  915.     return 0;
  916. }
  917.