home *** CD-ROM | disk | FTP | other *** search
/ Chip 1997 December / CHIPNET Aralık 1997.iso / linux / redhat / misc / src / install / devices.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-08-11  |  29.1 KB  |  1,141 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. #include <zlib.h>
  12.  
  13. #include "devices.h"
  14. #include "install.h"
  15. #include "log.h"
  16. #include "net.h"
  17. #include "perror.h"
  18. #include "run.h"
  19. #include "scsi.h"
  20. #include "windows.h"
  21.  
  22. #define MODULES_PATH "/modules/"
  23.  
  24. static char * plipDevice = NULL;        /* hack */
  25.  
  26. struct devnum {
  27.     char * name;
  28.     short major, minor;
  29.     int isChar;
  30. };
  31.  
  32. const static struct devnum devices[] = {
  33.     { "aztcd",        29,    0,    0 },
  34.     { "bpcd",        41,    0,    0 },
  35.     { "cdu31a",        15,    0,    0 },
  36.     { "cdu535",        24,    0,    0 },
  37.     { "cm206cd",    32,    0,    0 },
  38.     { "fd0",         2,    0,    0 },
  39.     { "fd1",        2,    1,    0 },
  40.     { "gscd",        16,    0,    0 },
  41.     { "lp0",        6,    0,    1 },
  42.     { "lp1",        6,    1,    1 },
  43.     { "lp2",        6,    2,    1 },
  44.     { "mcd",        23,    0,    0 },
  45.     { "mcdx",        20,    0,    0 },
  46.     { "nst0",        9,    128,    1 },
  47.     { "optcd",        17,    0,    0 },
  48.     { "sbpcd",        25,    0,    0 },
  49.     { "scd0",        11,    0,    0 },
  50.     { "scd1",        11,    1,    0 },
  51.     { "sjcd",        18,    0,    0 },
  52. };
  53.  
  54. const int numDevices = sizeof(devices) / sizeof(struct devnum);
  55.  
  56. struct moduleOptions {
  57.     char * arg;
  58.     char * desc;
  59.     char * defaults;
  60. } ;
  61.  
  62. const struct moduleOptions neOptions[] = {
  63.    { "io", "Base IO port:", "0x300:0x280:0x320:0x340:0x360" },
  64.    { "irq", "IRQ level:", NULL },
  65.    { NULL, NULL, NULL }
  66. } ;
  67.  
  68. const struct moduleOptions de4x5Options[] = {
  69.    { "io", "Base IO port:", "0x0b" },
  70.    { NULL, NULL, NULL }
  71. } ;
  72.  
  73. const struct moduleOptions cdu31aOptions[] = {
  74.    { "cdu31a", "IO base, IRQ, PAS?:", "" },
  75.    { NULL, NULL, NULL }
  76. } ;
  77.  
  78. const struct moduleOptions cm206Options[] = {
  79.    { "cm206", "IO base, IRQ:", "" },
  80.    { NULL, NULL, NULL }
  81. } ;
  82.  
  83. const struct moduleOptions mcdOptions[] = {
  84.    { "mcd", "IO base address:", "" },
  85.    { NULL, NULL, NULL }
  86. } ;
  87.  
  88. const struct moduleOptions optcdOptions[] = {
  89.    { "optcd", "IO base address:", "" },
  90.    { NULL, NULL, NULL }
  91. } ;
  92.  
  93. const struct moduleOptions sbpcdOptions[] = {
  94.    { "sbpcd", "IO base, IRQ, label:", "" },
  95.    { NULL, NULL, NULL }
  96. } ;
  97.  
  98. #define MODULE_AUTOPROBE    (1 << 0)
  99. #define MODULE_FAKEAUTOPROBE    (1 << 1)
  100.  
  101. struct moduleInfo {
  102.     char * name;
  103.     int shouldAutoprobe;
  104.     const struct moduleOptions * options;
  105.     int flags;
  106.     char * defaultOptions;
  107. } ;
  108.  
  109. /* keep this alphabetical! */
  110. struct moduleInfo modules[] = { 
  111.     { "8390", 1, NULL, 0, NULL },
  112.     { "cdu31a", 0, cdu31aOptions, 0, NULL },
  113.     { "cm206", 0, cm206Options, 0, NULL },
  114.     { "de4x5", 1, de4x5Options, MODULE_AUTOPROBE, "io=0" },
  115.     { "ds", 1, NULL, 0, NULL },
  116.     { "i82365", 1, NULL, 0, NULL },
  117.     { "isofs", 1, NULL, 0, NULL },
  118.     { "loop", 1, NULL, 0, NULL },
  119.     { "lp", 1, NULL, 0, NULL },
  120.     { "mcd", 0, mcdOptions, 0, NULL },
  121.     { "ne", 0, neOptions, MODULE_FAKEAUTOPROBE, "io=0x300" },
  122.     { "nfs", 1, NULL, 0, NULL },
  123.     { "optcd", 0, optcdOptions, 0, NULL },
  124.     { "pcmcia_core", 1, NULL, 0, NULL },
  125.     { "sbpcd", 1, sbpcdOptions, 0, NULL },
  126.     { "smbfs", 1, NULL, 0, NULL },
  127.     { "tcic", 1, NULL, 0, NULL },
  128.     { NULL, 0, NULL, 0, NULL }                /* sentinel */
  129. } ;
  130.  
  131. struct driver {
  132.     char * name;
  133.     char * modules;
  134.     int isLoaded;
  135.     driverOkayFn okay;
  136.     enum driverTypes type;
  137.     enum driverMinor minor;
  138. };
  139.  
  140. static int checkEthernetDev(struct driver * dev);
  141. static int checkSCSIDev(struct driver * dev);
  142. static int checkPlipDev(struct driver * dev);
  143. static int checkTokenRingDev(struct driver * dev);
  144.  
  145. static struct driver drivers[] = {
  146.     { "3com 3c509", "3c509", 0, checkEthernetDev, 
  147.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  148.     { "3com 3c59x (Vortex)", "3c59x", 0, checkEthernetDev,
  149.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  150.     { "3com 3c90x (Boomerang)", "3c59x", 0, checkEthernetDev,
  151.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  152.     { "3com 3c501", "3c501", 0, checkEthernetDev, 
  153.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  154.     { "3com 3c503", "8390:3c503", 0, checkEthernetDev, 
  155.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  156.     { "Allied Telesis AT1700", "at1700", 0, checkEthernetDev, 
  157.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  158.     { "Apricot 82596", "apricot", 0, checkEthernetDev, 
  159.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  160.     { "Cabletron E2100", "8390:e2100", 0, checkEthernetDev, 
  161.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  162.     { "Digital 425,434,435,450,500", "de4x5", 0, checkEthernetDev, 
  163.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  164.     { "Digital DEPCA and EtherWORKS", "depca", 0, checkEthernetDev, 
  165.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  166.     { "Digital EtherWORKS 3", "ewrk3", 0, checkEthernetDev, 
  167.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  168.     { "Digital 21040 (Tulip)", "tulip", 0, checkEthernetDev, 
  169.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  170.     { "D-Link DE-600 pocket adapter", "de600", 0, checkEthernetDev, 
  171.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  172.     { "D-Link DE-620 pocket adapter", "de620", 0, checkEthernetDev, 
  173.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  174.     { "HP10/100VG any LAN ", "hp100", 0, checkEthernetDev, 
  175.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  176.     { "HP LAN/AnyLan", "hp", 0, checkEthernetDev, 
  177.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  178.     { "HP PCLAN/plus", "8390:hp-plus", 0, checkEthernetDev, 
  179.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  180.     { "Intel EtherExpress", "eexpress", 0, checkEthernetDev, 
  181.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  182.     { "Intel EtherExpress Pro", "eepro", 0, checkEthernetDev, 
  183.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  184.     { "Intel EtherExpress Pro 100", "eepro100", 0, checkEthernetDev, 
  185.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  186.     { "NE2000 and compatible", "8390:ne", 0, checkEthernetDev, 
  187.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  188.     { "NI 5210", "ni52", 0, checkEthernetDev, 
  189.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  190.     { "NI 6510", "ni65", 0, checkEthernetDev, 
  191.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  192.     { "PLIP (parallel port)", "plip", 0, checkPlipDev, 
  193.         DRIVER_NET, DRIVER_MINOR_PLIP },
  194.     { "SMC 9000 series", "smc9194", 0, checkEthernetDev, 
  195.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  196.     { "SMC Ultra ethernet", "8390:smc-ultra", 0, checkEthernetDev, 
  197.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  198.     { "Token Ring", "ibmtr", 0, checkTokenRingDev, 
  199.         DRIVER_NET, DRIVER_MINOR_TR },
  200.     { "WD8003, WD8013 and compatible", "8390:wd", 0, checkEthernetDev,
  201.         DRIVER_NET, DRIVER_MINOR_ETHERNET },
  202.  
  203.     { "Adaptec 152x", "aha152x", 0, checkSCSIDev,
  204.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  205.     { "Adaptec 1542", "aha1542", 0, checkSCSIDev,
  206.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  207.     { "Adaptec 1740", "aha1740", 0, checkSCSIDev,
  208.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  209.     { "Adaptec 2740, 2840, 2940", "aic7xxx", 0, checkSCSIDev,
  210.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  211.     { "AdvanSys Adapters", "advansys", 0, checkSCSIDev,
  212.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  213.     { "Always IN2000", "in2000", 0, checkSCSIDev,
  214.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  215.     { "Buslogic Adapters", "BusLogic", 0, checkSCSIDev,
  216.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  217.     { "DTC 3180/3280", "dtc", 0, checkSCSIDev,
  218.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  219.     { "EATA DMA Adapters", "eata_dma", 0, checkSCSIDev,
  220.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  221.     { "EATA PIO Adapters", "eata_pio", 0, checkSCSIDev,
  222.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  223.     { "Future Domain TMC-885, TMC-950", "seagate", 0, checkSCSIDev,
  224.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  225.     { "Future Domain TMC-16x0", "fdomain", 0, checkSCSIDev,
  226.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  227.     { "Iomega PPA3 (parallel port Zip)", "ppa", 0, checkSCSIDev,
  228.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  229.     { "NCR 5380", "g_NCR5380", 0, checkSCSIDev,
  230.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  231.     { "NCR 53c406a", "NCR53c406a", 0, checkSCSIDev,
  232.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  233.     { "NCR 53C810/53C820 PCI", "53c7,8xx", 0, checkSCSIDev,
  234.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  235.     { "NCR 53C810/53C820 (alternate)", "ncr53c8xx", 0, checkSCSIDev,
  236.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  237.     { "Pro Audio Spectrum/Studio 16", "pas16", 0, checkSCSIDev,
  238.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  239.     { "Qlogic FAS", "qlogicfas", 0, checkSCSIDev,
  240.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  241.     { "Qlogic ISP", "qlogicisp", 0, checkSCSIDev,
  242.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  243.     { "Seagate ST01/02", "seagate", 0, checkSCSIDev,
  244.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  245.     { "Trantor T128/T128F/T228", "t128", 0, checkSCSIDev,
  246.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  247.     { "UltraStor 14F/34F", "u14-34f", 0, checkSCSIDev,
  248.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  249.     { "UltraStor 14F/24F/34F", "ultrastor", 0, checkSCSIDev,
  250.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  251.     { "Western Digital wd7000", "wd7000", 0, checkSCSIDev,
  252.         DRIVER_SCSI, DRIVER_MINOR_NONE },
  253.  
  254.     { "PCMCIA core support", "pcmcia_core", 0, NULL,
  255.         DRIVER_PCMCIA, DRIVER_MINOR_NONE },
  256.     { "PCMCIA card support", "ds", 0, NULL,
  257.         DRIVER_PCMCIA, DRIVER_MINOR_NONE },
  258.     { "PCMCIA i82365 controller", "i82365", 0, NULL,
  259.         DRIVER_PCMCIA, DRIVER_MINOR_NONE },
  260.     { "PCMCIA tcic controller", "tcic", 0, NULL,
  261.         DRIVER_PCMCIA, DRIVER_MINOR_NONE },
  262.  
  263.     { "iso9660", "isofs", 0, NULL,
  264.         DRIVER_FS, DRIVER_MINOR_NONE },
  265.     { "Network File System (nfs)", "nfs", 0, NULL,
  266.         DRIVER_FS, DRIVER_MINOR_NONE },
  267.     { "Windows SMB", "smbfs", 0, NULL,
  268.         DRIVER_FS, DRIVER_MINOR_NONE },
  269.  
  270.     { "Aztech CD", "aztcd", 0, NULL,
  271.         DRIVER_CDROM, DRIVER_MINOR_NONE },
  272.     { "Backpack CDROM", "bpcd", 0, NULL,
  273.         DRIVER_CDROM, DRIVER_MINOR_NONE },
  274.     { "Goldstar R420", "gscd", 0, NULL,
  275.         DRIVER_CDROM, DRIVER_MINOR_NONE },
  276.     { "Mitsumi", "mcd", 0, NULL,
  277.         DRIVER_CDROM, DRIVER_MINOR_NONE },
  278.     { "Mitsumi (alternate)", "mcdx", 0, NULL,
  279.         DRIVER_CDROM, DRIVER_MINOR_NONE },
  280.     { "Optics Storage 8000", "optcd", 0, NULL,
  281.         DRIVER_CDROM, DRIVER_MINOR_NONE },
  282.     { "Phillips CM206/CM260", "cm206:cdrom", 0, NULL,
  283.         DRIVER_CDROM, DRIVER_MINOR_NONE },
  284.     { "Sanyo", "sjcd", 0, NULL, 
  285.         DRIVER_CDROM, DRIVER_MINOR_NONE },
  286.     { "Sony CDU-31A", "cdu31a", 0, NULL, 
  287.         DRIVER_CDROM, DRIVER_MINOR_NONE },
  288.     { "Sony CDU-5xx", "sonycd535", 0, NULL, 
  289.         DRIVER_CDROM, DRIVER_MINOR_NONE },
  290.     { "SoundBlaster/Panasonic", "sbpcd", 0, NULL, 
  291.         DRIVER_CDROM, DRIVER_MINOR_NONE },
  292.  
  293.     { "Loopback device", "loop", 0, NULL, DRIVER_OTHER, DRIVER_MINOR_NONE },
  294.     { "Parallel Printer", "lp", 0, NULL, DRIVER_OTHER, DRIVER_MINOR_NONE },
  295.  
  296.     { NULL, NULL, 0, NULL, DRIVER_OTHER }, /* sentinel */
  297. };
  298.  
  299. static const int numDrivers = sizeof(drivers) / sizeof(struct driver);
  300.  
  301. static int loadDeviceModule(struct driver * driver, 
  302.                 struct driversLoaded ** drlist);
  303. static int getOptions(const char * name, int * argcp, char *** argvp);
  304. static struct driversLoaded * allocDL(struct driversLoaded ** drlist);
  305.  
  306. int devMakeInode(char * name, char * path) {
  307.     int i;
  308.     int major, minor;
  309.     int type;
  310.  
  311.     if (name[0] == 's' && name[1] == 'd') {
  312.     type = S_IFBLK;
  313.     major = 8;
  314.     minor = (name[2] - 'a') << 4;
  315.     if (name[3] && name[4]) 
  316.        minor += 10 + (name[4] - '0');
  317.     else if (name[3])
  318.        minor += (name[3] - '0');
  319.     } else if (name[0] == 'h' && name[1] == 'd') {
  320.     type = S_IFBLK;
  321.     if (name[2] == 'a') 
  322.         major = 3, minor = 0;
  323.     else if (name[2] == 'b')
  324.         major = 3, minor = 64;
  325.     else if (name[2] == 'c')
  326.         major = 22, minor = 0;
  327.     else if (name[2] == 'd')
  328.         major = 22, minor = 64;
  329.     else if (name[2] == 'e')
  330.         major = 33, minor = 0;
  331.     else if (name[2] == 'f')
  332.         major = 33, minor = 64;
  333.     else if (name[2] == 'g')
  334.         major = 34, minor = 0;
  335.     else if (name[2] == 'h')
  336.         major = 34, minor = 64;
  337.     else
  338.         return INST_ERROR;
  339.  
  340.     if (name[3] && name[4]) 
  341.        minor += 10 + (name[4] - '0');
  342.     else if (name[3])
  343.        minor += (name[3] - '0');
  344.     } else if (!strncmp(name, "ram", 3)) {
  345.     type = S_IFBLK;
  346.     major = 1;
  347.     minor = 1;
  348.     if (name[3])
  349.         minor += name[3] - '1';
  350.     } else {
  351.     for (i = 0; i < numDevices; i++) {
  352.         if (!strcmp(devices[i].name, name)) break;
  353.     }
  354.     if (i == numDevices) return INST_ERROR;
  355.     major = devices[i].major;
  356.     minor = devices[i].minor;
  357.  
  358.     if (devices[i].isChar)
  359.         type = S_IFCHR;
  360.     else
  361.         type = S_IFBLK;
  362.     }
  363.  
  364.     logMessage("making device %s (%d, %d) as %s", name, major, minor, path);
  365.  
  366.     if (testing)
  367.     messageWindow("mknod", "making device %s (%d, %d) as %s", 
  368.               name, major, minor, path);
  369.  
  370.     unlink(path);
  371.     if (mknod(path, type | 0600, makedev(major, minor))) {
  372.     messageWindow("Error", perrorstr("mknod() failed"));
  373.     return INST_ERROR;
  374.     }
  375.  
  376.     return 0;
  377. }
  378.  
  379. void devRemoveInode(char * path) {
  380.     logMessage("removing device file %s", path);
  381.     unlink(path);
  382. }
  383.  
  384. static int modulesPanel(enum driverTypes type, struct driver ** drvptr) {
  385.     int drCount = 0;
  386.     int i;
  387.     newtComponent label, f, listbox;
  388.     newtComponent okay, answer, cancel;
  389.  
  390.     for (i = 0; i < numDrivers; i++) {
  391.     if (drivers[i].type == type) drCount++;
  392.     }
  393.  
  394.     newtOpenWindow(17, 4, 45, 15, "Load module");
  395.  
  396.     f = newtForm(NULL, NULL, 0);
  397.     label = newtLabel(1, 1, "Which driver should I try?");
  398.     newtFormAddComponent(f, label);
  399.  
  400.     listbox = newtListbox(5, 3, 6, NEWT_LISTBOX_RETURNEXIT);
  401.  
  402.     drCount = 0;
  403.     for (i = 0; i < numDrivers; i++) {
  404.     if (drivers[i].type == type) {
  405.         newtListboxAddEntry(listbox, drivers[i].name, drivers + i);
  406.         drCount++;
  407.     }
  408.     }
  409.  
  410.     newtFormAddComponent(f, listbox);
  411.     okay = newtButton(8, 10, "Ok");
  412.     cancel = newtButton(28, 10, "Cancel");
  413.  
  414.     newtFormAddComponents(f, okay, cancel, NULL);
  415.  
  416.     answer = newtRunForm(f);
  417.  
  418.     if (answer == cancel) {
  419.     newtFormDestroy(f);
  420.     newtPopWindow();
  421.     return INST_CANCEL;
  422.     }
  423.  
  424.     *drvptr = newtListboxGetCurrent(listbox);
  425.  
  426.     newtFormDestroy(f);
  427.     newtPopWindow();
  428.  
  429.     return 0;
  430. }
  431.  
  432. int loadDeviceDriver(enum driverTypes type, struct driversLoaded ** drlist) {
  433.     struct driver * driver;
  434.     int rc;
  435.  
  436.     do {
  437.     rc = modulesPanel(type, &driver);
  438.     if (rc) return rc;
  439.  
  440.     rc = loadDeviceModule(driver, drlist);
  441.     if (rc == INST_ERROR) {
  442.         errorWindow("I can't find the device anywhere on your system!");
  443.     }
  444.     } while (rc);
  445.  
  446.     return 0;
  447. }
  448.  
  449. static int loadDeviceModule(struct driver * driver, 
  450.                 struct driversLoaded ** drlist) {
  451.     char * start, * chptr, ** modStack;
  452.     char moduleName[100];
  453.     int rc;
  454.     int nummods = 1;
  455.     enum driverTypes type;
  456.    
  457.     chptr = start = driver->modules;
  458.     while (*chptr) {
  459.     if (*chptr == ':') nummods++;
  460.     chptr++;
  461.     }
  462.  
  463.     modStack = alloca(sizeof(char *) * (nummods + 1));
  464.  
  465.     nummods = 0;
  466.     while (start && *start) {
  467.     chptr = strchr(start, ':');
  468.     if (chptr) {
  469.         strncpy(moduleName, start, chptr - start);
  470.         moduleName[chptr - start] = '\0';
  471.         start = chptr + 1;
  472.         type = DRIVER_PREREQ;
  473.     } else {
  474.         strcpy(moduleName, start);
  475.         start = NULL;
  476.         type = driver->type;
  477.     }
  478.  
  479.     if ((rc = loadModule(moduleName, type, driver->minor, drlist))) {
  480.         while (nummods) {
  481.         removeModule(modStack[--nummods]);
  482.         }
  483.         return rc;
  484.     }
  485.  
  486.     
  487.     modStack[nummods] = alloca(strlen(moduleName) + 1);
  488.     strcpy(modStack[nummods++], moduleName);
  489.     }
  490.  
  491.     if (driver->okay && !driver->okay(driver)) {
  492.     while (nummods) {
  493.         removeModule(modStack[--nummods]);
  494.     }
  495.     logMessage("device check function failed to find device");
  496.     return INST_ERROR;
  497.     }
  498.  
  499.     return 0;
  500. }
  501.  
  502. int removeModule(char * module) {
  503.     char * argv[] = { "/bin/rmmod", NULL, NULL };
  504.  
  505.     argv[1] = module;
  506.  
  507.     return runProgram(RUN_LOG, "/bin/rmmod", argv);
  508. }
  509.  
  510. char * getPlipDeviceName(void) {
  511.      return plipDevice;
  512. }
  513.  
  514. int loadModule(char * modName, enum driverTypes type, enum driverMinor minor,
  515.            struct driversLoaded ** drlist) {
  516.     struct driversLoaded * dl;
  517.     char * objName;
  518.     char ** argv;
  519.     int argc;
  520.     int rc;
  521.     int fd;
  522.     int rmObj = 0;
  523.     int clearWindow = 0;
  524.     gzFile stream;
  525.     char buf[4096];
  526.     int i = 0;
  527.  
  528.     if (type == DRIVER_SCSI) {
  529.     winStatus(35, 3, "SCSI", "Scanning SCSI bus...");
  530.     clearWindow = 1;
  531.     }
  532.  
  533.     objName = alloca(strlen(modName) + 15 + strlen(MODULES_PATH));
  534.  
  535.     strcpy(objName, MODULES_PATH);
  536.     strcat(objName, modName);
  537.     strcat(objName, ".o");
  538.  
  539. #ifdef __i386__
  540.     if (access(objName, R_OK)) {
  541.     /* it might be gzipped */
  542.     strcat(objName, ".gz");
  543.     if (access(objName, R_OK)) {
  544.         logMessage("can't find module %s", modName);
  545.         return INST_ERROR;
  546.     }
  547.  
  548.     stream = gzopen(objName, "r");
  549.     if (!stream) {
  550.         logMessage("gzopen failed to read %s: %s", objName, 
  551.             strerror(errno));
  552.         return INST_ERROR;
  553.     }
  554.  
  555.     strcpy(objName, "/tmp/");
  556.     strcat(objName, modName);
  557.     strcat(objName, ".o");
  558.     if ((fd = open(objName, O_WRONLY | O_CREAT | O_TRUNC)) < 0) {
  559.         logMessage("failed to create %s: %s", objName, strerror(errno));
  560.         gzclose(stream);
  561.         return INST_ERROR;
  562.     }
  563.  
  564.     logMessage("uncompressing module for installation");
  565.  
  566.     while ((i = gzread(stream, buf, sizeof(buf))) > 0) {
  567.         if (write(fd, buf, i) != i) {
  568.         logMessage("write() failed during module decompression: %s\n",
  569.                strerror(errno));
  570.         close(fd);
  571.         gzclose(stream);
  572.         return INST_ERROR;
  573.         }
  574.     }
  575.  
  576.     if (i < 0)
  577.         logMessage("write() failed during module decompression: %s\n",
  578.                strerror(errno));
  579.  
  580.     close(fd);
  581.     gzclose(stream);
  582.     if (i < 0) return INST_ERROR;
  583.  
  584.     rmObj = 1;
  585.     }
  586. #endif
  587.  
  588.     argc = 2;
  589.     argv = malloc((argc + 1) * sizeof(char *));
  590.     argv[0] = "/bin/insmod";
  591.     argv[1] = objName;
  592.     argv[2] = NULL;
  593.  
  594.     if ((rc = getOptions(modName, &argc, &argv))) {
  595.     free(argv);
  596.     if (clearWindow) newtPopWindow();
  597.     return rc;
  598.     } 
  599.  
  600.     if (runProgram(RUN_LOG, "/bin/insmod", argv)) {
  601.     free(argv);
  602.     logMessage("insmod failed!");
  603.     if (clearWindow) newtPopWindow();
  604.     return INST_ERROR;
  605.     }
  606.  
  607.     if (drlist) { 
  608.     dl = allocDL(drlist);
  609.  
  610.     dl->type = type;
  611.     dl->minor = minor;
  612.     dl->argv = argv;
  613.     dl->argc = argc;
  614.     dl->module = strdup(modName);
  615.     dl->persistFlags = 0;
  616.     }
  617.  
  618.     if (clearWindow) newtPopWindow();
  619.     if (rmObj) unlink(objName);
  620.  
  621.     return 0;
  622. }
  623.  
  624. static struct driversLoaded * allocDL(struct driversLoaded ** drlist) {
  625.     struct driversLoaded * new;
  626.  
  627.     if (*drlist == NULL) {
  628.     *drlist = malloc(sizeof(**drlist));
  629.     new = *drlist;
  630.     } else {
  631.     new = *drlist;
  632.     while (new->next) new = new->next;
  633.     new->next = malloc(sizeof(**drlist));
  634.     new = new->next;
  635.     }
  636.  
  637.     new->next = NULL;
  638.  
  639.     return new;
  640. }
  641.  
  642. #define OPTIONS_SPECIFY ((void *) 1)
  643. #define OPTIONS_DEFAULT ((void *) 2)
  644.  
  645. static int getOptions(const char * name, int * argcp, char *** argvp) {
  646.     newtComponent form, listbox, text, okay, answer, cancel;
  647.     char ** parameters = NULL;
  648.     char * miscParameters;
  649.     char buf[2000];
  650.     struct moduleInfo * mod;
  651.     void * choice;
  652.     int numOptions, col, miscRow, buttonRow, i;
  653.     const struct moduleOptions * option;
  654.     char * miscText;
  655.     char * chptr, * start;
  656.  
  657.     mod = modules;
  658.     while (mod->name) {
  659.     if (!strcmp(mod->name, name)) break;
  660.     mod++;
  661.     }
  662.     if (!mod->name) mod = NULL;
  663.     
  664.     if (mod && !mod->options) {
  665.     (*argcp)++;
  666.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  667.     (*argvp)[(*argcp) - 1] = mod->defaultOptions;
  668.     (*argvp)[(*argcp)] = NULL;
  669.     if (!mod->defaultOptions)
  670.         (*argcp)--;
  671.     
  672.     return 0;
  673.     }
  674.  
  675.     if (!mod || mod->shouldAutoprobe) {
  676.     sprintf(buf, "In some cases, the %s driver needs to have extra "
  677.         "information to work properly, although it normally works "
  678.         "fine without. Would you like to specify extra options "
  679.         "for it or allow the driver to probe your machine for the "
  680.         "information it needs? Occasionally, probing will hang a "
  681.         "computer, but it should not cause any damage.", name);
  682.  
  683.     newtOpenWindow(10, 4, 60, 16, "Module Options");
  684.     listbox = newtListbox(20, 9, 0, NEWT_LISTBOX_RETURNEXIT);
  685.     newtListboxAddEntry(listbox, "Autoprobe", OPTIONS_DEFAULT);
  686.     newtListboxAddEntry(listbox, "Specify options", OPTIONS_SPECIFY);
  687.     buttonRow = 12;
  688.     } else {
  689.     sprintf(buf, "In many cases, the %s driver needs to be provided with "
  690.         "extra information on your hardware. If you prefer, "
  691.         "some common values for those parameters will be tried. "
  692.         "This process can hang a machine, although it should "
  693.         "not cause any damage.", name);
  694.     newtOpenWindow(10, 5, 60, 14, "Module Options");
  695.     listbox = newtListbox(20, 7, 0, NEWT_LISTBOX_RETURNEXIT);
  696.     newtListboxAddEntry(listbox, "Specify options", OPTIONS_SPECIFY);
  697.     newtListboxAddEntry(listbox, "Autoprobe", OPTIONS_DEFAULT);
  698.     buttonRow = 10;
  699.     }
  700.  
  701.     text = newtTextbox(1, 1, 55, 7, NEWT_TEXTBOX_WRAP);
  702.     newtTextboxSetText(text, buf);
  703.  
  704.     okay = newtButton(13, buttonRow, "Ok");
  705.     cancel = newtButton(39, buttonRow, "Cancel");
  706.  
  707.     form = newtForm(NULL, NULL, 0);
  708.     newtFormAddComponents(form, text, listbox, okay, cancel, NULL);
  709.  
  710.     answer = newtRunForm(form);
  711.     newtPopWindow();
  712.  
  713.     choice = newtListboxGetCurrent(listbox);
  714.     newtFormDestroy(form);
  715.  
  716.     if (answer == cancel) {
  717.     return INST_CANCEL;
  718.     }
  719.  
  720.     if (choice == OPTIONS_DEFAULT) {
  721.     (*argcp)++;
  722.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  723.     if (mod)
  724.         (*argvp)[(*argcp) - 1] = mod->defaultOptions;
  725.     (*argvp)[(*argcp)] = NULL;
  726.     if (!mod || !mod->defaultOptions)
  727.         (*argcp)--;
  728.     
  729.     return 0;
  730.     }
  731.  
  732.     form = newtForm(NULL, NULL, 0);
  733.     newtFormAddComponent(form, newtLabel(1, 1, "Module options:"));
  734.  
  735.     numOptions = 0;
  736.     col = 0;
  737.     if (mod) {
  738.     option = mod->options;
  739.     while (option->arg) {
  740.         newtFormAddComponent(form, newtLabel(3, 3 + numOptions, 
  741.                  option->desc));
  742.         if (strlen(option->desc) > col) col = strlen(option->desc);
  743.         numOptions++;
  744.         option++;
  745.     }
  746.     miscText = "Miscellaneous options:";
  747.     } else {
  748.     miscText = "Module options:";
  749.     }
  750.  
  751.     if (numOptions) 
  752.     miscRow = 4 + numOptions; 
  753.     else
  754.     miscRow = 3;
  755.  
  756.     newtFormAddComponent(form, newtLabel(3, miscRow, "Miscellaneous options:"));
  757.  
  758.     if (22 > col) col = 22;
  759.  
  760.     if (numOptions) {
  761.     parameters = alloca(sizeof(*parameters) * numOptions);
  762.     numOptions = 0;
  763.     option = mod->options;
  764.     while (option->arg) {
  765.         sprintf(buf, "%s=", option->arg);
  766.         newtFormAddComponent(form, newtEntry(col + 5, 3 + numOptions, 
  767.                  buf, 20, parameters + numOptions, 
  768.                  NEWT_ENTRY_SCROLL));
  769.         numOptions++;
  770.         option++;
  771.     }
  772.     }
  773.  
  774.     newtFormAddComponent(form, newtEntry(col + 5, miscRow, "", 20,
  775.              &miscParameters, NEWT_ENTRY_SCROLL));
  776.  
  777.     newtOpenWindow((80 - (col + 30)) / 2, (25 - (miscRow + 6)) / 2, col + 30,
  778.             miscRow + 6, "Module Parameters");
  779.  
  780.     okay = newtButton((col + 10) / 3, miscRow + 2, "Ok");
  781.     cancel = newtButton(10 + 2 * ((col + 10) / 3), miscRow + 2, "Cancel");
  782.     newtFormAddComponents(form, okay, cancel, NULL);
  783.  
  784.     answer = newtRunForm(form);
  785.  
  786.     newtPopWindow();
  787.  
  788.     if (answer == cancel) {
  789.     newtFormDestroy(form);
  790.     return INST_CANCEL;
  791.     }
  792.  
  793.     if (mod) {
  794.     i = *argcp;
  795.     (*argcp) += numOptions;
  796.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  797.     numOptions = 0;
  798.      
  799.     option = mod->options;
  800.     while (option->arg) {
  801.         sprintf(buf, "%s=", option->arg);
  802.         if (strcmp(parameters[numOptions], buf))
  803.         (*argvp)[i++] = strdup(parameters[numOptions]);
  804.         numOptions++, option++;
  805.     }
  806.     (*argcp) = i;
  807.     }
  808.  
  809.     chptr = miscParameters;
  810.     numOptions = 0;
  811.     while (*chptr) {
  812.     while (isspace(*chptr) && *chptr) chptr++;
  813.     if (!*chptr) continue;
  814.     
  815.     numOptions++;
  816.     while (!isspace(*chptr) && *chptr) chptr++;
  817.     }
  818.  
  819.     i = *argcp;
  820.     (*argcp) += numOptions;
  821.     (*argvp) = realloc(*argvp, (*argcp + 1) * sizeof(char *));
  822.     numOptions = 0;
  823.  
  824.     chptr = miscParameters;
  825.     numOptions = 0;
  826.     while (*chptr) {
  827.     while (isspace(*chptr) && *chptr) chptr++;
  828.     if (!*chptr) continue;
  829.     
  830.     start = chptr;
  831.     numOptions++;
  832.     while (!isspace(*chptr) && *chptr) chptr++;
  833.  
  834.     if (*chptr) {
  835.         *chptr = '\0';
  836.         (*argvp)[i++] = strdup(start);
  837.         *chptr = ' ';
  838.     } else
  839.         (*argvp)[i++] = strdup(start);
  840.     }
  841.     (*argcp) = i;
  842.     (*argvp)[*argcp] = NULL;
  843.  
  844.     newtFormDestroy(form);
  845.  
  846.     return 0;
  847. }
  848.  
  849. int readModuleConfPersist(char * prefix, struct driversLoaded * drlist) {
  850.     char buf[255];
  851.     FILE * f;
  852.     char * start, * end, * chptr;
  853.     enum driverTypes type;
  854.     enum driverMinor minor;
  855.     struct driversLoaded * dl;
  856.  
  857.     strcpy(buf, prefix);
  858.     strcat(buf, "/conf.modules");
  859.  
  860.     f = fopen(buf, "r");
  861.     if (!f) {
  862.     logMessage("failed to open %s for module information", prefix);
  863.     return INST_ERROR;
  864.     }
  865.  
  866.     while (fgets(buf, sizeof(buf) - 1, f)) {
  867.      start = buf;
  868.     end = start + strlen(start) - 1;
  869.     *end = '\0';
  870.  
  871.     if (!strncmp(start, "alias ", 6)) {
  872.         start += 6;
  873.  
  874.         type = DRIVER_OTHER;
  875.         minor = DRIVER_MINOR_NONE;
  876.  
  877.         while (isspace(*start) && *start) start++;
  878.  
  879.         if (!strncmp(start, "eth0", 4)) {
  880.         type = DRIVER_NET;
  881.         minor = DRIVER_MINOR_ETHERNET;
  882.         start += 5;
  883.         } else if (!strncmp(start, "scsi_hostadapter", 16)) {
  884.         type = DRIVER_SCSI;
  885.         start += 17;
  886.         }
  887.  
  888.         if (type != DRIVER_OTHER) {
  889.         dl = drlist;
  890.         while (dl) {
  891.             if (dl->type == type && dl->minor == minor) break;
  892.             dl = dl->next;
  893.         }
  894.  
  895.         while (isspace(*start) && *start) start++;
  896.  
  897.         if (dl && *start && !strcmp(start, dl->module)) {
  898.             dl->persistFlags |= PERSIST_ALIAS;
  899.         }
  900.         }
  901.     } else if (!strncmp(start, "options ", 8)) {
  902.         start += 8;
  903.  
  904.         chptr = start;
  905.         while (!isspace(*chptr) && *chptr) chptr++;
  906.         if (!*chptr) continue;
  907.         
  908.         *chptr = '\0';
  909.  
  910.         dl = drlist;
  911.         while (dl) {
  912.         if (!strcmp(dl->module, start)) break;
  913.         dl = dl->next;
  914.         }
  915.  
  916.         if (dl) {
  917.         /* we really should check that these options match the
  918.            ones we used, but that's nontrivial FIXME */
  919.         dl->persistFlags |= PERSIST_OPTIONS;
  920.         }
  921.     }
  922.     }
  923.  
  924.     fclose(f);
  925.  
  926.     return 0;
  927. }
  928.  
  929. int readModuleConf(char * prefix, struct driversLoaded ** drlist) {
  930.     char buf[255];
  931.     FILE * f;
  932.     char * start, * end, * chptr;
  933.     struct driversLoaded * item = NULL;
  934.  
  935.     if (testing) return 0;
  936.  
  937.     strcpy(buf, prefix);
  938.     strcat(buf, "/conf.modules");
  939.  
  940.     f = fopen(buf, "r");
  941.     if (!f) {
  942.     return INST_ERROR;
  943.     }
  944.  
  945.     while (fgets(buf, sizeof(buf) - 1, f)) {
  946.      start = buf;
  947.     end = start + strlen(start) - 1;
  948.     *end = '\0';
  949.  
  950.     if (!strncmp(start, "alias ", 6)) {
  951.         start += 6;
  952.  
  953.         if (!strncmp(start, "eth", 3)) {
  954.         start += 5;
  955.  
  956.         item = allocDL(drlist);
  957.  
  958.         item->module = strdup(start);
  959.         item->argv = NULL;
  960.         item->argc = 0;
  961.         item->persistFlags = 0;
  962.         item->type = DRIVER_NET;
  963.         item->minor = DRIVER_MINOR_ETHERNET;
  964.         } else if (!strncmp(start, "scsi_hostadapter", 16)) {
  965.         start += 17;
  966.         while (isspace(*start) && *start) start++;
  967.         if (!*start) continue;
  968.  
  969.         item = allocDL(drlist);
  970.  
  971.         item->module = strdup(start);
  972.         item->argv = NULL;
  973.         item->argc = 0;
  974.         item->persistFlags = 0;
  975.         item->type = DRIVER_SCSI;
  976.         item->minor = DRIVER_MINOR_NONE;
  977.         }
  978.     } else if (!strncmp(start, "options ", 8)) {
  979.         start += 8;
  980.  
  981.         chptr = start;
  982.         while (!isspace(*chptr) && *chptr) chptr++;
  983.         if (!*chptr) continue;
  984.         
  985.         *chptr = '\0';
  986.         
  987.         item = *drlist;
  988.         while (item && strcmp(item->module, start)) item = item->next; 
  989.  
  990.         if (!item) {
  991.         item = allocDL(drlist);
  992.         item->module = strdup(start);
  993.         item->argv = NULL;
  994.         item->argc = 0;
  995.         item->persistFlags = 0;
  996.         item->type = DRIVER_NET;
  997.         item->minor = DRIVER_MINOR_ETHERNET;
  998.         }
  999.  
  1000.         item->argv = malloc(sizeof(char *) * 5);
  1001.         item->argc = 3;
  1002.         item->argv[2] = strdup(chptr + 1);
  1003.     }
  1004.     }
  1005.  
  1006.     fclose(f);
  1007.  
  1008.     return 0;
  1009. }
  1010.  
  1011. int writeModuleConf(char * prefix, struct driversLoaded * dl, int append) {
  1012.     char buf[255];
  1013.     char buf2[255];
  1014.     FILE * f;
  1015.     int i;
  1016.     char * mode = append ? "a" : "w";
  1017.  
  1018.     if (testing) return 0;
  1019.  
  1020.     strcpy(buf, prefix);
  1021.     strcat(buf, "/conf.modules");
  1022.  
  1023.     if (!append && !access(buf, F_OK)) {
  1024.     logMessage("backing up old conf.modules");
  1025.     strcpy(buf2, buf);
  1026.     strcat(buf2, ".orig");
  1027.     rename(buf, buf2);
  1028.     }
  1029.  
  1030.     f = fopen(buf, mode);
  1031.     if (!f) {
  1032.     errorWindow("cannot open module config file: %s");
  1033.     return INST_ERROR;
  1034.     }
  1035.  
  1036.     while (dl) {
  1037.     if (dl->type == DRIVER_NET) {
  1038.         if (!append || !(dl->persistFlags & PERSIST_ALIAS))
  1039.         fprintf(f, "alias eth0 %s\n", dl->module);
  1040.     }
  1041.     else if (dl->type == DRIVER_SCSI) {
  1042.         if (!append || !(dl->persistFlags & PERSIST_ALIAS))
  1043.         fprintf(f, "alias scsi_hostadapter %s\n", dl->module);
  1044.     }
  1045.  
  1046.     if (!append || !(dl->persistFlags & PERSIST_OPTIONS)) {
  1047.         if (dl->argc > 2) {
  1048.         fprintf(f, "options %s", dl->module);
  1049.         for (i = 2; i < dl->argc; i++) {
  1050.             fprintf(f, " %s", dl->argv[i]);
  1051.         }
  1052.         
  1053.         fprintf(f, "\n");
  1054.         }
  1055.     }
  1056.  
  1057.     dl = dl->next;
  1058.     }
  1059.  
  1060.     fclose(f);
  1061.  
  1062.     return 0;
  1063. }
  1064.  
  1065. static int checkSCSIDev(struct driver * dev) {
  1066.     return scsiDeviceAvailable();
  1067. }
  1068.  
  1069. static int checkEthernetDev(struct driver * dev) {
  1070.     return netDeviceAvailable("eth0");
  1071. }
  1072.  
  1073. static int checkTokenRingDev(struct driver * dev) {
  1074.     return netDeviceAvailable("tr0");
  1075. }
  1076.  
  1077. static int checkPlipDev(struct driver * dev) {
  1078.     plipDevice = NULL;
  1079.  
  1080.     if (netDeviceAvailable("plip0")) {
  1081.     logMessage("plip0 will be used for PLIP");
  1082.     plipDevice = "plip0";
  1083.     } else if (netDeviceAvailable("plip1")) {
  1084.     logMessage("plip1 will be used for PLIP");
  1085.     plipDevice = "plip1";
  1086.     } else if (netDeviceAvailable("plip2")) {
  1087.     logMessage("plip2 will be used for PLIP");
  1088.     plipDevice = "plip2";
  1089.     }
  1090.     
  1091.     return (plipDevice != NULL);
  1092. }
  1093.  
  1094. /* This assumes only one of each driver type is loaded */
  1095. int removeDeviceDriver(enum driverTypes type, struct driversLoaded ** drlist) {
  1096.     char * buf, * chptr;
  1097.     struct driversLoaded * dl, * head;
  1098.     struct driver * dri;
  1099.  
  1100.     dl = *drlist;
  1101.     while (dl && dl->type != type) {
  1102.     dl = dl->next;
  1103.     }
  1104.     if (!dl) return 0;
  1105.  
  1106.     dri = drivers;
  1107.     while (dri->name) {
  1108.     if (!strcmp(dri->modules, dl->module)) break;
  1109.     dri++;
  1110.     }
  1111.  
  1112.     if (!dri->name) return 0;
  1113.  
  1114.     buf = alloca(strlen(dri->modules) + 1);
  1115.     strcpy(buf, dri->modules);
  1116.  
  1117.     chptr = buf + strlen(buf) - 1;
  1118.     while (chptr > buf) {
  1119.     while (chptr > buf && *chptr != ':') chptr--;
  1120.     if (*chptr == ':') {
  1121.         chptr = '\0';
  1122.         removeModule(chptr + 1);
  1123.         chptr--;
  1124.     }
  1125.     }
  1126.  
  1127.     removeModule(buf);
  1128.  
  1129.     if (dl == *drlist) {
  1130.     *drlist = dl->next;
  1131.     free(dl);
  1132.     } else if (dl) {
  1133.     head = *drlist;
  1134.     while (head->next != dl) head = head->next;
  1135.     head->next = dl->next;
  1136.     free(dl);
  1137.     }
  1138.  
  1139.     return 0;
  1140. }
  1141.