/* * config.c - Read configuration file for makerom * * Copyright (C) 1998-2003 Gero Kuhlmann * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * $Id: doconfig.c,v 1.6 2003/03/09 00:43:08 gkminix Exp $ */ #include #include #include "makerom.h" #include "doconfig.h" #include "md5.h" /* * Maximum execution size */ #define MAX_EXEC_SIZE (128L * 1024L) /* * Default path and file name definitions */ #define DRIVERFILE "//netboot.drivers" #define MD5SUMFILE "//netdrvr/MD5SUMS" #define BINDIR "//binaries" #define NETDRVDIR "//netdrvr" #define UTILSDIR "//utils://binaries" #define KERNEL32 "kernel.bin" #define KERNEL16 "kernel86.bin" #define KERNELM "kernelm.bin" #define ROM32 "rom.bin" #define ROM16 "rom86.bin" #define FLOPPY32 "floppy.bin" #define FLOPPY16 "floppy86.bin" #define PKTDRV32 "netpkt.bin" #define PKTDRV16 "netpkt86.bin" #define NDIS32 "netndis.bin" #define NDIS16 "netndis86.bin" #define UNDI32 "netundi.bin" #define UNDI16 "netundi86.bin" /* * Global variables */ struct confstruct config; /* configuration information */ /* * Local variables */ static char *tmpdrvfname = NULL; /* temporary drivers file name */ static char *tmpmd5fname = NULL; /* temporary MD5 sums file name */ /* * Definition of makerom:general section in configuration file */ static struct paramdef general_params[] = { { "driverfile", par_string, NULL, {&tmpdrvfname}}, { "md5sumfile", par_string, NULL, {&tmpmd5fname}}, { "bindir", par_string, NULL, {&config.bindir}}, { "netdrvdir", par_string, NULL, {&config.netdrvdir}}, { "utilsdir", par_string, NULL, {&config.utilsdir}}, { "kernel32", par_string, NULL, {&config.files[FILE_KERNEL].filename32}}, { "kernel16", par_string, NULL, {&config.files[FILE_KERNEL].filename16}}, { "kernelm32", par_string, NULL, {&config.files[FILE_KERNELM].filename32}}, { "kernelm16", par_string, NULL, {&config.files[FILE_KERNELM].filename16}}, { "rom32", par_string, NULL, {&config.files[FILE_ROM].filename32}}, { "rom16", par_string, NULL, {&config.files[FILE_ROM].filename16}}, { "floppy32", par_string, NULL, {&config.files[FILE_FLOPPY].filename32}}, { "floppy16", par_string, NULL, {&config.files[FILE_FLOPPY].filename16}}, { NULL, par_null, NULL, {NULL}} }; /* * Assign a new string to a string pointer */ static void assignstr(old, new) char **old; char *new; { if (new != NULL) { if (*old != NULL) free(*old); *old = new; } } /* * Read network driver interface information from configuration file */ static char *dsections[] = { "pktdrv", "ndis", "undi" }; static struct { char *filename32; char *filename16; char *description; char *directory; char *pattern; } netdrv_vars; static struct paramdef netdrv_params[] = { { "filename32", par_string, NULL, {&netdrv_vars.filename32}}, { "filename16", par_string, NULL, {&netdrv_vars.filename16}}, { "description", par_string, NULL, {&netdrv_vars.description}}, { "directory", par_string, NULL, {&netdrv_vars.directory}}, { "pattern", par_string, NULL, {&netdrv_vars.pattern}}, { NULL, par_null, NULL, {NULL}} }; static char *handle_netdrv_sect(sectname, cursect) char *sectname; struct sectdef *cursect; { struct netdrvinfo *ip; int drvtype; char *cp; /* Determine name of section, e.g. driver interface type */ assert((cp = strrchr(sectname, ':')) != NULL); cp++; for (drvtype = DRVTYPE_MIN; drvtype <= DRVTYPE_MAX; drvtype++) if (!strcmp(cp, dsections[drvtype - DRVTYPE_MIN])) break; if (drvtype > DRVTYPE_MAX) { if (netdrv_vars.description != NULL) free(netdrv_vars.description); if (netdrv_vars.directory != NULL) free(netdrv_vars.directory); if (netdrv_vars.pattern != NULL) free(netdrv_vars.pattern); if (netdrv_vars.filename32 != NULL) free(netdrv_vars.filename32); if (netdrv_vars.filename16 != NULL) free(netdrv_vars.filename16); memset(&netdrv_vars, 0, sizeof(netdrv_vars)); return("invalid network driver interface section"); } /* Add new item to info list */ ip = &config.netdrv[drvtype]; assignstr(&(ip->descript), netdrv_vars.description); assignstr(&(ip->searchdir), netdrv_vars.directory); assignstr(&(ip->patlist), netdrv_vars.pattern); assignstr(&(ip->filename32), netdrv_vars.filename32); assignstr(&(ip->filename16), netdrv_vars.filename16); /* Clear out temporary space for next round */ memset(&netdrv_vars, 0, sizeof(netdrv_vars)); return(NULL); } /* * List of recognized options for network driver binary files */ static struct { char *optname; int optval; } netoptlist[] = { { "HW_IRQ", HW_IRQ }, { "IO_ADDR", IO_ADDR }, { "BASE_MEM", BASE_MEM }, { "AUI_TYPE", AUI_TYPE }, { "DMA_NUM", DMA_NUM }, { NULL, 0 } }; static int getoption(optstr) char *optstr; { char *cp; int i, len, optval = 0; cp = optstr; while (cp != NULL) { cp += strspn(cp, " \t"); len = strcspn(cp, " \t,"); if (len > 0) { for (i = 0; netoptlist[i].optname != NULL; i++) if (strlen(netoptlist[i].optname) == len && !strncmp(netoptlist[i].optname, cp, len)) break; if (netoptlist[i].optname == NULL) return(-1); optval |= netoptlist[i].optval; } if ((cp = strchr(cp, ',')) != NULL) cp++; } return(optval); } /* * Find a network driver description in the configuration file structure. If * none is found, a new entry is generated and inserted into the description * list. */ static struct filedesc *getfiledesc(sectname) char *sectname; { struct filedesc *fp = config.drvdesc; char *cp; /* Determine driver name from section name */ assert((cp = strchr(sectname, ':')) != NULL); if (!*(++cp)) return(NULL); /* Find driver description in list */ while (fp != NULL) { if (!strcmp(fp->name, cp)) break; fp = fp->next; } /* Create new description record if not found */ if (fp == NULL) { fp = (struct filedesc *)nbmalloc(sizeof(struct filedesc)); copystr(&(fp->name), cp); fp->next = config.drvdesc; config.drvdesc = fp; } return(fp); } /* * Eliminate beginning and ending quotes from a string */ static char *delquotes(str) char *str; { int i; assert(str != NULL); if (str[0] == '"') { i = strlen(str); if (str[i - 1] != '"') return(NULL); str[i - 1] = '\0'; str++; } return(str); } /* * Read description string from config file. This routine gets called * everytime a "description" parameter is found in the config file. */ static struct descstr *desclist = NULL; static char *readdesc(name, arg) char *name; char *arg; { struct descstr *dp; /* Eliminate quotes from argument */ if ((arg = delquotes(arg)) == NULL) return("missing end quote"); /* Add new item to description string list */ dp = (struct descstr *)nbmalloc(sizeof(struct descstr)); copystr(&(dp->descript), arg); dp->next = desclist; desclist = dp; return(NULL); } /* * Delete a description string list */ static void deldesc(sp) struct descstr *sp; { struct descstr *spt; while (sp != NULL) { if (sp->descript != NULL) free(sp->descript); spt = sp; sp = sp->next; free(spt); } } /* * Read network card information from configuration file */ static char *btypes[] = { "ISA", "EISA", "MCA", "PCI", NULL }; static struct { char *usedriver; char *pnp_devid; int pci_vendid; int pci_devid; int bustype; } card_vars; static struct paramdef card_params[] = { { "description", par_proc, NULL, {(char **)&readdesc}}, { "bustype", par_enum, btypes, {(char **)&card_vars.bustype}}, { "pcivendor", par_int, NULL, {(char **)&card_vars.pci_vendid}}, { "pcidevice", par_int, NULL, {(char **)&card_vars.pci_devid}}, { "pnpdevid", par_string, NULL, {&card_vars.pnp_devid}}, { "usedriver", par_string, NULL, {&card_vars.usedriver}}, { NULL, par_null, NULL, {NULL}} }; static char *handle_card_sect(sectname, cursect) char *sectname; struct sectdef *cursect; { struct filedesc *fp; struct descstr *sp; char *cp = NULL; /* Analyze section name and create new item in description list */ if ((fp = getfiledesc(sectname)) == NULL) cp = "invalid section name"; else { /* Check that the bus type doesn't change from a previous definition */ if (card_vars.bustype != BUSTYPE_NONE) { if (fp->bustype != BUSTYPE_NONE && fp->bustype != card_vars.bustype) { if (cp == NULL) cp = "bus type already defined differently"; } else fp->bustype = card_vars.bustype; } /* Check that a PCI vendor/device ID doesn't change */ if (card_vars.pci_vendid != 0) { if (fp->pci_vendid != 0 && fp->pci_vendid != card_vars.pci_vendid) { if (cp == NULL) cp = "PCI vendor ID already defined differently"; } else fp->pci_vendid = card_vars.pci_vendid; } if (card_vars.pci_devid != 0) { if (fp->pci_devid != 0 && fp->pci_devid != card_vars.pci_devid) { if (cp == NULL) cp = "PCI device ID already defined differently"; } else fp->pci_devid = card_vars.pci_devid; } /* Check that the PnP device ID is correct and doesn't change */ if (card_vars.pnp_devid != NULL) { if (fp->pnp_devid != NULL && strcmp(card_vars.pnp_devid, fp->pnp_devid)) { if (cp == NULL) cp = "PnP device ID already defined differently"; } else if (strlen(card_vars.pnp_devid) > 0 && (strlen(card_vars.pnp_devid) != PNPIDLEN || !isalpha(card_vars.pnp_devid[0]) || !isalpha(card_vars.pnp_devid[1]) || !isalpha(card_vars.pnp_devid[2]) || !isxdigit(card_vars.pnp_devid[3]) || !isxdigit(card_vars.pnp_devid[4]) || !isxdigit(card_vars.pnp_devid[5]) || !isxdigit(card_vars.pnp_devid[6]))) { if (cp == NULL) cp = "invalid PnP device ID string"; } else { if (strlen(card_vars.pnp_devid) == 0) { free(card_vars.pnp_devid); card_vars.pnp_devid = NULL; if (fp->pnp_devid != NULL) free(fp->pnp_devid); fp->pnp_devid = NULL; } else { assignstr(&(fp->pnp_devid), card_vars.pnp_devid); card_vars.pnp_devid = NULL; } } } /* Check that the bus type is correct */ if (cp == NULL && fp->bustype != BUSTYPE_PCI && (fp->pci_vendid != 0 || fp->pci_devid != 0)) cp = "PCI vendor/device ID specified for non-PCI bus type"; if (cp == NULL && fp->bustype == BUSTYPE_PCI && fp->pnp_devid != NULL) cp = "PnP device ID string defined for PCI bus type"; if (cp == NULL && fp->pnp_devid != NULL && (fp->pci_vendid != 0 || fp->pci_devid != 0)) cp = "PCI vendor/device ID and PnP device ID defined"; /* Add driver cross-reference */ assignstr(&(fp->usedriver), card_vars.usedriver); card_vars.usedriver = NULL; /* Add list of descriptions to item */ if ((sp = desclist) != NULL) { while (sp->next != NULL) sp = sp->next; sp->next = fp->descript; fp->descript = desclist; } desclist = NULL; } /* Clear all dynamic memory which hasn't been saved so far */ deldesc(desclist); desclist = NULL; if (card_vars.pnp_devid != NULL) free(card_vars.pnp_devid); if (card_vars.usedriver != NULL) free(card_vars.usedriver); memset(&card_vars, 0, sizeof(card_vars)); return(cp); } /* * Read network driver information from configuration file */ static char *dtypes[] = { "packet driver", "ndis driver", "undi driver", NULL }; static struct { char *filename; char *parameters; char *pd_cmdline; char *ndis_protini; char *drvdesc; char *md5sum; int drvtype; long minsize; long maxsize; } driver_vars; static struct paramdef driver_params[] = { { "driverdesc", par_string, NULL, {&driver_vars.drvdesc}}, { "file", par_string, NULL, {&driver_vars.filename}}, { "params", par_string, NULL, {&driver_vars.parameters}}, { "cmdline", par_string, NULL, {&driver_vars.pd_cmdline}}, { "protini", par_string, NULL, {&driver_vars.ndis_protini}}, { "md5sum", par_string, NULL, {&driver_vars.md5sum}}, { "drvtype", par_enum, dtypes, {(char **)&driver_vars.drvtype}}, { "minsize", par_long, NULL, {(char **)&driver_vars.minsize}}, { "maxsize", par_long, NULL, {(char **)&driver_vars.maxsize}}, { NULL, par_null, NULL, {NULL}} }; static char *handle_driver_sect(sectname, cursect) char *sectname; struct sectdef *cursect; { struct filedesc *fp; struct drvdesc *dp; char *drvdesc = NULL; char *cp = NULL; char *mdp; int opt = -1; /* Analyze section name and create new item in description list */ if ((fp = getfiledesc(sectname)) == NULL) cp = "invalid section name"; else { /* Check that parameter combinations are valid */ switch (driver_vars.drvtype) { case DRVTYPE_NONE: if (driver_vars.filename != NULL || driver_vars.parameters != NULL || driver_vars.minsize != -1L || driver_vars.maxsize != -1L || driver_vars.pd_cmdline != NULL || driver_vars.ndis_protini != NULL || driver_vars.md5sum != NULL || driver_vars.drvdesc != NULL) cp = "missing driver type parameter"; break; case DRVTYPE_PD: if (driver_vars.ndis_protini != NULL) cp = "bogus \'protini\' parameter in packet driver definition"; break; case DRVTYPE_NDIS: if (driver_vars.pd_cmdline != NULL) cp = "bogus \'cmdline\' parameter in NDIS driver definition"; break; case DRVTYPE_UNDI: if (driver_vars.parameters != NULL) cp = "bogus \'params\' parameter in UNDI driver definition"; else if (driver_vars.ndis_protini != NULL) cp = "bogus \'protini\' parameter in UNDI driver definition"; else if (driver_vars.pd_cmdline != NULL) cp = "bogus \'cmdline\' parameter in UNDI driver definition"; else if (driver_vars.minsize != -1L || driver_vars.maxsize != -1L) cp = "bogus \'minsize\' or \'maxsize\' parameter in UNDI driver definition"; break; default: assert(driver_vars.drvtype >= DRVTYPE_MIN && driver_vars.drvtype <= DRVTYPE_MAX); break; } /* Analyze options */ if (driver_vars.parameters != NULL) { if ((opt = getoption(driver_vars.parameters)) < 0 && cp == NULL) cp = "invalid \'params\' parameter"; free(driver_vars.parameters); driver_vars.parameters = NULL; } /* Analyze execution sizes */ if (driver_vars.minsize < -2L) driver_vars.minsize = -2L; if (driver_vars.maxsize < -2L) driver_vars.maxsize = -2L; if (cp == NULL && ((driver_vars.minsize > 0L && driver_vars.maxsize > 0L && driver_vars.minsize > driver_vars.maxsize) || driver_vars.minsize > MAX_EXEC_SIZE || driver_vars.maxsize > MAX_EXEC_SIZE)) cp = "invalid execution size values"; /* Check for correct driver description string */ if (driver_vars.drvdesc != NULL && (drvdesc = delquotes(driver_vars.drvdesc)) == NULL) { if (cp == NULL) cp = "missing end quotes in network driver description string"; } /* Check for correct MD5 sum string, and convert it to lower case */ if (driver_vars.md5sum != NULL) { for (mdp = driver_vars.md5sum; *mdp; mdp++) { *mdp = tolower(*mdp); if ((*mdp < '0' || *mdp > '9') && (*mdp < 'a' || *mdp > 'f')) break; } if (cp == NULL && (mdp - driver_vars.md5sum) != MD5_SUM_LENGTH) cp = "invalid MD5 checksum string"; } /* Add new driver description record */ if (fp->usedriver != NULL) { if (cp == NULL) cp = "alternative driver list already defined"; } else if (driver_vars.drvtype != DRVTYPE_NONE) { dp = (struct drvdesc *)nbmalloc(sizeof(struct drvdesc)); dp->type = driver_vars.drvtype; switch (driver_vars.drvtype) { case DRVTYPE_PD: if (opt >= 0) dp->drv.pd.options = opt; dp->drv.pd.minsize = driver_vars.minsize; dp->drv.pd.maxsize = driver_vars.maxsize; assignstr(&(dp->drv.pd.cmdline), driver_vars.pd_cmdline); driver_vars.pd_cmdline = NULL; break; case DRVTYPE_NDIS: if (opt >= 0) dp->drv.ndis.options = opt; dp->drv.ndis.minsize = driver_vars.minsize; dp->drv.ndis.maxsize = driver_vars.maxsize; assignstr(&(dp->drv.ndis.protini), driver_vars.ndis_protini); driver_vars.ndis_protini = NULL; break; case DRVTYPE_UNDI: break; } if (driver_vars.drvdesc != NULL) { if (drvdesc != NULL) copystr(&(dp->descript), drvdesc); free(driver_vars.drvdesc); driver_vars.drvdesc = NULL; } assignstr(&(dp->filename), driver_vars.filename); assignstr(&(dp->md5sum), driver_vars.md5sum); driver_vars.filename = NULL; driver_vars.md5sum = NULL; dp->next = fp->drvlist; fp->drvlist = dp; } } /* Clear all dynamic memory before returning */ if (driver_vars.filename != NULL) free(driver_vars.filename); if (driver_vars.parameters != NULL) free(driver_vars.parameters); if (driver_vars.pd_cmdline != NULL) free(driver_vars.pd_cmdline); if (driver_vars.ndis_protini != NULL) free(driver_vars.ndis_protini); if (driver_vars.md5sum != NULL) free(driver_vars.md5sum); if (driver_vars.drvdesc != NULL) free(driver_vars.drvdesc); memset(&driver_vars, 0, sizeof(driver_vars)); driver_vars.minsize = -1L; driver_vars.maxsize = -1L; return(cp); } /* * List of sections to read from configuration files at startup */ static struct sectdef confsects[] = { { "makerom:general", general_params, NULL, NULL }, { NULL, NULL, NULL, NULL} }; static struct sectdef driversects[] = { { "netdrv:*", netdrv_params, NULL, &handle_netdrv_sect }, { "card:*", card_params, NULL, &handle_card_sect }, { "driver:*", driver_params, NULL, &handle_driver_sect }, { NULL, NULL, NULL, NULL} }; /* * Set configuration structure with default values */ static struct { char **cnfptr; char *defstr; } filedefaults[] = { { &config.bindir, BINDIR }, { &config.netdrvdir, NETDRVDIR }, { &config.utilsdir, UTILSDIR }, { &config.files[FILE_KERNEL].filename32, KERNEL32 }, { &config.files[FILE_KERNEL].filename16, KERNEL16 }, { &config.files[FILE_KERNELM].filename32, KERNELM }, { &config.files[FILE_ROM].filename32, ROM32 }, { &config.files[FILE_ROM].filename16, ROM16 }, { &config.files[FILE_FLOPPY].filename32, FLOPPY32 }, { &config.files[FILE_FLOPPY].filename16, FLOPPY16 }, { &config.netdrv[DRVTYPE_PD].filename32, PKTDRV32 }, { &config.netdrv[DRVTYPE_PD].filename16, PKTDRV16 }, { &config.netdrv[DRVTYPE_NDIS].filename32, NDIS32 }, { &config.netdrv[DRVTYPE_NDIS].filename16, NDIS16 }, { &config.netdrv[DRVTYPE_UNDI].filename32, UNDI32 }, { &config.netdrv[DRVTYPE_UNDI].filename16, UNDI16 }, { NULL, NULL } }; static char *netdescstr[] = { "Packet Driver interface (PD)", "Network Driver Interface Specification (NDIS)", "Universal Network Driver Interface (UNDI)" }; static char *netpathstr[] = { "pktdrvr:pktdrvr/drivers", "ndis2:ndis2/drivers", "undi:undi/drivers" }; static char *patternstr[] = { "*.com:*.exe", "*.sys:*.dos", "*.undi" }; static void setdefaults() { int i; /* Clearout configuration structure */ memset(&config, 0, sizeof(config)); /* Copy default strings into structure */ for (i = 0; filedefaults[i].defstr != NULL; i++) copystr(filedefaults[i].cnfptr, filedefaults[i].defstr); /* Set defaults for network driver interface definitions */ for (i = DRVTYPE_MIN; i <= DRVTYPE_MAX; i++) { copystr(&config.netdrv[i].descript, netdescstr[i - DRVTYPE_MIN]); copystr(&config.netdrv[i].searchdir, netpathstr[i - DRVTYPE_MIN]); copystr(&config.netdrv[i].patlist, patternstr[i - DRVTYPE_MIN]); } } /* * Normalize directory and file names and cleanup the network driver * description list. */ static void donormalize() { struct filedesc *fp; struct drvdesc *dp, *olddp, *dpt; char *sdir; int i; /* Normalize main directory names */ setpath(&config.bindir, NULL); setpath(&config.netdrvdir, NULL); setpath(&config.utilsdir, NULL); /* Normalize binary file names */ for (i = 0; i < FILE_NUMBER; i++) { checkaccess(&config.files[i].filename32, config.bindir); checkaccess(&config.files[i].filename16, config.bindir); } for (i = DRVTYPE_MIN; i <= DRVTYPE_MAX; i++) { setpath(&config.netdrv[i].searchdir, config.netdrvdir); checkaccess(&config.netdrv[i].filename32, config.bindir); checkaccess(&config.netdrv[i].filename16, config.bindir); } /* Scan through all network cards and process their drivers */ fp = config.drvdesc; while (fp != NULL) { /* Normalize network driver file names and check MD5 checksums */ dp = fp->drvlist; while (dp != NULL) { assert(dp->type >= DRVTYPE_MIN && dp->type <= DRVTYPE_MAX); sdir = NULL; switch (dp->type) { case DRVTYPE_PD: sdir = config.netdrv[DRVTYPE_PD].searchdir; break; case DRVTYPE_NDIS: sdir = config.netdrv[DRVTYPE_NDIS].searchdir; break; case DRVTYPE_UNDI: sdir = config.netdrv[DRVTYPE_UNDI].searchdir; break; } checkaccess(&(dp->filename), sdir); checkmd5sum(&(dp->filename), dp->md5sum); dp = dp->next; } /* * Remove all drivers with the same file name but without an MD5 * checksum, if at least one driver has a checksum. We have to do * this in a seperate loop because all filenames have to be * normalized first. */ dp = fp->drvlist; while (dp != NULL) { if (dp->filename != NULL && dp->md5sum != NULL) { dpt = fp->drvlist; while (dpt != NULL) { if (dpt != dp && dpt->md5sum == NULL && dpt->filename != NULL && !strcmp(dpt->filename, dp->filename)) { free(dpt->filename); dpt->filename = NULL; } dpt = dpt->next; } } dp = dp->next; } /* Cleanup driver list by deleting all drivers with empty filename */ dp = fp->drvlist; olddp = NULL; while (dp != NULL) { if (dp->filename == NULL) { /* Delete item from list */ switch (dp->type) { case DRVTYPE_PD: if (dp->drv.pd.cmdline != NULL) free(dp->drv.pd.cmdline); break; case DRVTYPE_NDIS: if (dp->drv.ndis.protini != NULL) free(dp->drv.ndis.protini); break; case DRVTYPE_UNDI: break; } if (dp->md5sum != NULL) free(dp->md5sum); if (dp->descript != NULL) free(dp->descript); if (olddp == NULL) fp->drvlist = dp->next; else olddp->next = dp->next; dpt = dp; dp = dp->next; free(dpt); } else { /* Continue with next item */ olddp = dp; dp = dp->next; } } fp = fp->next; } } /* * Resolve cross-reference driver lists and cleanup network card list */ static void doresolve() { struct filedesc *fp, *oldfp, *fpt; char *cp; fp = config.drvdesc; oldfp = NULL; while (fp != NULL) { fpt = NULL; if (fp->drvlist == NULL && (cp = fp->usedriver) != NULL) { fpt = config.drvdesc; while (fpt != NULL) { if (fpt != fp && !strcmp(fpt->name, cp)) break; fpt = fpt->next; } } if (fpt != NULL) fp->drvlist = fpt->drvlist; if (fp->drvlist == NULL) { /* Delete item from list */ deldesc(fp->descript); if (fp->name != NULL) free(fp->name); if (fp->pnp_devid != NULL) free(fp->pnp_devid); if (fp->usedriver != NULL) free(fp->usedriver); if (oldfp == NULL) config.drvdesc = fp->next; else oldfp->next = fp->next; fpt = fp; fp = fp->next; free(fpt); } else { oldfp = fp; fp = fp->next; } } } /* * Parse options and read configuration file */ void doconfig(argc, argv, opts) int argc; char **argv; struct cmdopt *opts; { /* Clear config file read structures */ memset(&netdrv_vars, 0, sizeof(netdrv_vars)); memset(&card_vars, 0, sizeof(card_vars)); memset(&driver_vars, 0, sizeof(driver_vars)); driver_vars.minsize = -1L; driver_vars.maxsize = -1L; /* Set defaults */ setdefaults(); /* Parse options and read configuration file */ nbsetup(argc, argv, opts, confsects); /* Let the command line file name override the one from the config file */ if (tmpmd5fname != NULL) { if (config.md5fname == NULL) config.md5fname = tmpmd5fname; else free(tmpmd5fname); tmpmd5fname = NULL; } else if (config.md5fname == NULL) copystr(&config.md5fname, MD5SUMFILE); /* Normalize name of MD5 sums file and read it */ checkaccess(&config.md5fname, NULL); if (config.md5fname != NULL) readmd5(config.md5fname); else prnerr0("WARNING: No or invalid MD5 checksum file specified!"); /* Let the command line file name override the one from the config file */ if (tmpdrvfname != NULL) { if (config.drvfname == NULL) config.drvfname = tmpdrvfname; else free(tmpdrvfname); tmpdrvfname = NULL; } else if (config.drvfname == NULL) copystr(&config.drvfname, DRIVERFILE); /* Normalize file name of network driver configuration file and read it */ checkaccess(&config.drvfname, NULL); if (config.drvfname != NULL) readconfig(driversects, config.drvfname); else prnerr0("WARNING: No or invalid network driver config file specified!"); /* Normalize directory and file names and resolve cross-references */ donormalize(); doresolve(); /* Cleanup MD5 checksum list, which is no longer needed */ clearmd5(); }