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