home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 February / CHIP_2_98.iso / misc / src / install / devices.c < prev    next >
C/C++ Source or Header  |  1997-11-09  |  37KB  |  1,412 lines

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