module.c revision 53993
138465Smsmith/*- 238465Smsmith * Copyright (c) 1998 Michael Smith <msmith@freebsd.org> 338465Smsmith * All rights reserved. 438465Smsmith * 538465Smsmith * Redistribution and use in source and binary forms, with or without 638465Smsmith * modification, are permitted provided that the following conditions 738465Smsmith * are met: 838465Smsmith * 1. Redistributions of source code must retain the above copyright 938465Smsmith * notice, this list of conditions and the following disclaimer. 1038465Smsmith * 2. Redistributions in binary form must reproduce the above copyright 1138465Smsmith * notice, this list of conditions and the following disclaimer in the 1238465Smsmith * documentation and/or other materials provided with the distribution. 1338465Smsmith * 1438465Smsmith * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1538465Smsmith * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1638465Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1738465Smsmith * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1838465Smsmith * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1938465Smsmith * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2038465Smsmith * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2138465Smsmith * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2238465Smsmith * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2338465Smsmith * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2438465Smsmith * SUCH DAMAGE. 2538465Smsmith * 2650477Speter * $FreeBSD: head/sys/boot/common/module.c 53993 1999-12-01 18:30:26Z dcs $ 2738465Smsmith */ 2838465Smsmith 2938465Smsmith/* 3038465Smsmith * module function dispatcher, support, etc. 3138465Smsmith */ 3238465Smsmith 3338465Smsmith#include <stand.h> 3438465Smsmith#include <string.h> 3540141Speter#include <sys/param.h> 3640141Speter#include <sys/linker.h> 3738465Smsmith 3838465Smsmith#include "bootstrap.h" 3938465Smsmith 4038764Smsmithstatic struct loaded_module *mod_loadmodule(char *name, int argc, char *argv[]); 4138764Smsmithstatic char *mod_searchdep(struct loaded_module *mp); 4239178Smsmithstatic char *mod_searchfile(char *name); 4338764Smsmithstatic char *mod_searchmodule(char *name); 4438764Smsmithstatic void mod_append(struct loaded_module *mp); 4538764Smsmith 4639178Smsmith/* load address should be tweaked by first module loaded (kernel) */ 4738465Smsmithstatic vm_offset_t loadaddr = 0; 4838465Smsmith 4940141Speterstatic char *default_searchpath ="/;/boot;/modules"; 5039178Smsmith 5138465Smsmithstruct loaded_module *loaded_modules = NULL; 5238465Smsmith 5338764Smsmith/* 5438764Smsmith * load an object, either a disk file or code module. 5538764Smsmith * 5638764Smsmith * To load a file, the syntax is: 5738764Smsmith * 5838764Smsmith * load -t <type> <path> 5938764Smsmith * 6038764Smsmith * code modules are loaded as: 6138764Smsmith * 6238764Smsmith * load <path> <options> 6338764Smsmith */ 6438764Smsmith 6538465SmsmithCOMMAND_SET(load, "load", "load a kernel or module", command_load); 6638465Smsmith 6738465Smsmithstatic int 6838465Smsmithcommand_load(int argc, char *argv[]) 6938465Smsmith{ 7038764Smsmith char *typestr; 7138764Smsmith int dofile, ch; 7238764Smsmith 7338764Smsmith dofile = 0; 7438764Smsmith optind = 1; 7542512Smsmith optreset = 1; 7638764Smsmith typestr = NULL; 7753993Sdcs if (argc == 1) { 7853993Sdcs command_errmsg = "no filename specified"; 7953993Sdcs return(CMD_ERROR); 8053993Sdcs } 8138764Smsmith while ((ch = getopt(argc, argv, "t:")) != -1) { 8238764Smsmith switch(ch) { 8338764Smsmith case 't': 8438764Smsmith typestr = optarg; 8538764Smsmith dofile = 1; 8638764Smsmith break; 8738764Smsmith case '?': 8838764Smsmith default: 8938764Smsmith /* getopt has already reported an error */ 9038764Smsmith return(CMD_OK); 9138764Smsmith } 9238764Smsmith } 9338764Smsmith argv += (optind - 1); 9438764Smsmith argc -= (optind - 1); 9538764Smsmith 9638764Smsmith /* 9738764Smsmith * Request to load a raw file? 9838764Smsmith */ 9938764Smsmith if (dofile) { 10038764Smsmith if ((typestr == NULL) || (*typestr == 0)) { 10138764Smsmith command_errmsg = "invalid load type"; 10238764Smsmith return(CMD_ERROR); 10338764Smsmith } 10438764Smsmith return(mod_loadobj(typestr, argv[1])); 10538764Smsmith } 10638764Smsmith 10738764Smsmith /* 10838764Smsmith * Looks like a request for a module. 10938764Smsmith */ 11038465Smsmith return(mod_load(argv[1], argc - 2, argv + 2)); 11138465Smsmith} 11238465Smsmith 11338712SmsmithCOMMAND_SET(unload, "unload", "unload all modules", command_unload); 11438712Smsmith 11538712Smsmithstatic int 11638712Smsmithcommand_unload(int argc, char *argv[]) 11738712Smsmith{ 11838712Smsmith struct loaded_module *mp; 11938712Smsmith 12038712Smsmith while (loaded_modules != NULL) { 12138712Smsmith mp = loaded_modules; 12238712Smsmith loaded_modules = loaded_modules->m_next; 12338764Smsmith mod_discard(mp); 12438712Smsmith } 12538712Smsmith loadaddr = 0; 12638712Smsmith return(CMD_OK); 12738712Smsmith} 12838712Smsmith 12938465SmsmithCOMMAND_SET(lsmod, "lsmod", "list loaded modules", command_lsmod); 13038465Smsmith 13138465Smsmithstatic int 13238465Smsmithcommand_lsmod(int argc, char *argv[]) 13338465Smsmith{ 13438465Smsmith struct loaded_module *am; 13538764Smsmith struct module_metadata *md; 13638465Smsmith char lbuf[80]; 13738764Smsmith int ch, verbose; 13838764Smsmith 13938764Smsmith verbose = 0; 14038764Smsmith optind = 1; 14142512Smsmith optreset = 1; 14238764Smsmith while ((ch = getopt(argc, argv, "v")) != -1) { 14338764Smsmith switch(ch) { 14438764Smsmith case 'v': 14538764Smsmith verbose = 1; 14638764Smsmith break; 14738764Smsmith case '?': 14838764Smsmith default: 14938764Smsmith /* getopt has already reported an error */ 15038764Smsmith return(CMD_OK); 15138764Smsmith } 15238764Smsmith } 15338764Smsmith 15438465Smsmith pager_open(); 15538465Smsmith for (am = loaded_modules; (am != NULL); am = am->m_next) { 15639673Sdfr sprintf(lbuf, " %p: %s (%s, 0x%lx)\n", 15739673Sdfr (void *) am->m_addr, am->m_name, am->m_type, (long) am->m_size); 15838465Smsmith pager_output(lbuf); 15938465Smsmith if (am->m_args != NULL) { 16038465Smsmith pager_output(" args: "); 16138465Smsmith pager_output(am->m_args); 16238465Smsmith pager_output("\n"); 16338465Smsmith } 16438764Smsmith if (verbose) 16538764Smsmith /* XXX could add some formatting smarts here to display some better */ 16638764Smsmith for (md = am->m_metadata; md != NULL; md = md->md_next) { 16739673Sdfr sprintf(lbuf, " 0x%04x, 0x%lx\n", md->md_type, (long) md->md_size); 16838764Smsmith pager_output(lbuf); 16938764Smsmith } 17038465Smsmith } 17138465Smsmith pager_close(); 17238465Smsmith return(CMD_OK); 17338465Smsmith} 17438465Smsmith 17538764Smsmith/* 17638764Smsmith * We've been asked to load (name) and give it (argc),(argv). 17738764Smsmith * Start by trying to load it, and then attempt to load all of its 17838764Smsmith * dependancies. If we fail at any point, throw them all away and 17938764Smsmith * fail the entire load. 18038764Smsmith * 18138764Smsmith * XXX if a depended-on module requires arguments, it must be loaded 18238764Smsmith * explicitly first. 18338764Smsmith */ 18438465Smsmithint 18538465Smsmithmod_load(char *name, int argc, char *argv[]) 18638465Smsmith{ 18738764Smsmith struct loaded_module *last_mod, *base_mod, *mp; 18838764Smsmith char *dep_name; 18938764Smsmith 19038764Smsmith /* remember previous last module on chain */ 19138764Smsmith for (last_mod = loaded_modules; 19238764Smsmith (last_mod != NULL) && (last_mod->m_next != NULL); 19338764Smsmith last_mod = last_mod->m_next) 19438764Smsmith ; 19538465Smsmith 19638764Smsmith /* 19738764Smsmith * Load the first module; note that it's the only one that gets 19838764Smsmith * arguments explicitly. 19938764Smsmith */ 20038764Smsmith if ((base_mod = mod_loadmodule(name, argc, argv)) == NULL) 20138764Smsmith return(CMD_ERROR); 20238465Smsmith 20338764Smsmith /* 20438764Smsmith * Look for dependancies. 20538764Smsmith */ 20638764Smsmith while ((dep_name = mod_searchdep(base_mod)) != NULL) { 20738764Smsmith printf("loading required module '%s'\n", dep_name); 20838764Smsmith if ((mp = mod_loadmodule(dep_name, 0, NULL)) == NULL) { 20938764Smsmith /* Load failed; discard everything */ 21038764Smsmith while (base_mod != NULL) { 21138764Smsmith mp = base_mod; 21238764Smsmith base_mod = base_mod->m_next; 21338764Smsmith mod_discard(mp); 21438764Smsmith } 21538764Smsmith last_mod->m_next = NULL; 21638764Smsmith loadaddr = last_mod->m_addr + last_mod->m_size; 21738764Smsmith /* error message already set by mod_loadmodule */ 21838764Smsmith return(CMD_ERROR); 21938764Smsmith } 22038764Smsmith } 22138764Smsmith return(CMD_OK); 22238764Smsmith} 22338764Smsmith 22438764Smsmith/* 22538764Smsmith * We've been asked to load (name) as (type), so just suck it in, 22638764Smsmith * no arguments or anything. 22738764Smsmith */ 22838764Smsmithint 22938764Smsmithmod_loadobj(char *type, char *name) 23038764Smsmith{ 23138764Smsmith struct loaded_module *mp; 23238764Smsmith char *cp; 23338764Smsmith int fd, got; 23438764Smsmith vm_offset_t laddr; 23538764Smsmith 23638764Smsmith /* We can't load first */ 23738764Smsmith if ((mod_findmodule(NULL, NULL)) == NULL) { 23838764Smsmith command_errmsg = "can't load file before kernel"; 23938764Smsmith return(CMD_ERROR); 24038764Smsmith } 24138764Smsmith 24239178Smsmith /* locate the file on the load path */ 24339178Smsmith cp = mod_searchfile(name); 24439178Smsmith if (cp == NULL) { 24539178Smsmith sprintf(command_errbuf, "can't find '%s'", name); 24639178Smsmith return(CMD_ERROR); 24739178Smsmith } 24839178Smsmith name = cp; 24938764Smsmith 25038764Smsmith if ((fd = open(name, O_RDONLY)) < 0) { 25138764Smsmith sprintf(command_errbuf, "can't open '%s': %s", name, strerror(errno)); 25244570Sdcs free(name); 25338764Smsmith return(CMD_ERROR); 25438764Smsmith } 25538764Smsmith 25638764Smsmith laddr = loadaddr; 25738764Smsmith for (;;) { 25838764Smsmith /* read in 4k chunks; size is not really important */ 25938764Smsmith got = archsw.arch_readin(fd, laddr, 4096); 26038764Smsmith if (got == 0) /* end of file */ 26138764Smsmith break; 26238764Smsmith if (got < 0) { /* error */ 26338764Smsmith sprintf(command_errbuf, "error reading '%s': %s", name, strerror(errno)); 26444210Sdcs free(name); 26538764Smsmith return(CMD_ERROR); 26638764Smsmith } 26738764Smsmith laddr += got; 26838764Smsmith } 26938764Smsmith 27038764Smsmith /* Looks OK so far; create & populate control structure */ 27138764Smsmith mp = malloc(sizeof(struct loaded_module)); 27244210Sdcs mp->m_name = name; 27338764Smsmith mp->m_type = strdup(type); 27438764Smsmith mp->m_args = NULL; 27538764Smsmith mp->m_metadata = NULL; 27638764Smsmith mp->m_loader = -1; 27738764Smsmith mp->m_addr = loadaddr; 27838764Smsmith mp->m_size = laddr - loadaddr; 27938764Smsmith 28038764Smsmith /* recognise space consumption */ 28138764Smsmith loadaddr = laddr; 28238764Smsmith 28338764Smsmith /* Add to the list of loaded modules */ 28438764Smsmith mod_append(mp); 28538764Smsmith return(CMD_OK); 28638764Smsmith} 28738764Smsmith 28838764Smsmith/* 28938764Smsmith * Load the module (name), pass it (argc),(argv). 29038764Smsmith * Don't do any dependancy checking. 29138764Smsmith */ 29238764Smsmithstatic struct loaded_module * 29338764Smsmithmod_loadmodule(char *name, int argc, char *argv[]) 29438764Smsmith{ 29538764Smsmith struct loaded_module *mp; 29638764Smsmith int i, err; 29738764Smsmith char *cp; 29838764Smsmith 29939178Smsmith /* locate the module on the search path */ 30039178Smsmith cp = mod_searchmodule(name); 30139178Smsmith if (cp == NULL) { 30239178Smsmith sprintf(command_errbuf, "can't find '%s'", name); 30339178Smsmith return(NULL); 30439178Smsmith } 30539178Smsmith name = cp; 30639178Smsmith 30738764Smsmith err = 0; 30838764Smsmith for (i = 0, mp = NULL; (module_formats[i] != NULL) && (mp == NULL); i++) { 30938764Smsmith if ((err = (module_formats[i]->l_load)(name, loadaddr, &mp)) != 0) { 31038764Smsmith 31138465Smsmith /* Unknown to this handler? */ 31238465Smsmith if (err == EFTYPE) 31338465Smsmith continue; 31438465Smsmith 31538465Smsmith /* Fatal error */ 31638465Smsmith sprintf(command_errbuf, "can't load module '%s': %s", name, strerror(err)); 31744570Sdcs free(name); 31838764Smsmith return(NULL); 31938712Smsmith } else { 32038764Smsmith 32138764Smsmith /* Load was OK, set args */ 32238764Smsmith mp->m_args = unargv(argc, argv); 32338764Smsmith 32438764Smsmith /* where can we put the next one? */ 32538764Smsmith loadaddr = mp->m_addr + mp->m_size; 32638764Smsmith 32738712Smsmith /* remember the loader */ 32838764Smsmith mp->m_loader = i; 32938764Smsmith 33038764Smsmith /* Add to the list of loaded modules */ 33138764Smsmith mod_append(mp); 33238764Smsmith 33338764Smsmith break; 33438465Smsmith } 33538465Smsmith } 33638764Smsmith if (err == EFTYPE) 33738764Smsmith sprintf(command_errbuf, "don't know how to load module '%s'", name); 33844570Sdcs free(name); 33938764Smsmith return(mp); 34038764Smsmith} 34138764Smsmith 34238764Smsmith/* 34338764Smsmith * Search the modules from (mp) onwards, and return the name of the 34438764Smsmith * first unresolved dependancy, or NULL if none were found. 34538764Smsmith */ 34638764Smsmithstatic char * 34738764Smsmithmod_searchdep(struct loaded_module *mp) 34838764Smsmith{ 34940141Speter char *deps; 35040141Speter size_t deplen; 35138764Smsmith struct module_metadata *md; 35238764Smsmith struct loaded_module *dmp; 35338764Smsmith int dindex; 35438764Smsmith 35538764Smsmith for (; mp != NULL; mp = mp->m_next) { 35638764Smsmith 35738764Smsmith /* 35838764Smsmith * Get KLD module data 35938764Smsmith */ 36038764Smsmith deps = NULL; 36140141Speter deplen = 0; 36240141Speter if ((md = mod_findmetadata(mp, MODINFOMD_DEPLIST)) != NULL) { 36340141Speter deps = (char *)md->md_data; 36440141Speter deplen = md->md_size; 36540141Speter } 36638465Smsmith 36740141Speter if (deps != NULL && deplen > 0) { 36838764Smsmith 36938764Smsmith /* Iterate over dependancies */ 37040141Speter dindex = 0; 37140141Speter while (dindex < deplen) { 37238764Smsmith /* 37338764Smsmith * Look for a module matching the dependancy; if we don't have it, 37438764Smsmith * we need it. 37538764Smsmith */ 37640141Speter if ((dmp = mod_findmodule(&deps[dindex], NULL)) == NULL) 37740141Speter return(&deps[dindex]); 37840141Speter dindex += strlen(&deps[dindex]) + 1; 37938764Smsmith } 38038764Smsmith } 38138465Smsmith } 38238764Smsmith return(NULL); 38338465Smsmith} 38438465Smsmith 38538764Smsmith/* 38638764Smsmith * Find a module matching (name) and (type). 38738764Smsmith * NULL may be passed as a wildcard to either. 38838764Smsmith */ 38938465Smsmithstruct loaded_module * 39038465Smsmithmod_findmodule(char *name, char *type) 39138465Smsmith{ 39238465Smsmith struct loaded_module *mp; 39338465Smsmith 39438465Smsmith for (mp = loaded_modules; mp != NULL; mp = mp->m_next) { 39538465Smsmith if (((name == NULL) || !strcmp(name, mp->m_name)) && 39638465Smsmith ((type == NULL) || !strcmp(type, mp->m_type))) 39738465Smsmith break; 39838465Smsmith } 39938465Smsmith return(mp); 40038465Smsmith} 40138712Smsmith 40238764Smsmith/* 40338764Smsmith * Make a copy of (size) bytes of data from (p), and associate them as 40438764Smsmith * metadata of (type) to the module (mp). 40538764Smsmith */ 40638712Smsmithvoid 40738712Smsmithmod_addmetadata(struct loaded_module *mp, int type, size_t size, void *p) 40838712Smsmith{ 40938712Smsmith struct module_metadata *md; 41038712Smsmith 41138712Smsmith md = malloc(sizeof(struct module_metadata) + size); 41238712Smsmith md->md_size = size; 41338712Smsmith md->md_type = type; 41438712Smsmith bcopy(p, md->md_data, size); 41538712Smsmith md->md_next = mp->m_metadata; 41638712Smsmith mp->m_metadata = md; 41738712Smsmith} 41838712Smsmith 41938764Smsmith/* 42038764Smsmith * Find a metadata object of (type) associated with the module 42138764Smsmith * (mp) 42238764Smsmith */ 42338712Smsmithstruct module_metadata * 42438712Smsmithmod_findmetadata(struct loaded_module *mp, int type) 42538712Smsmith{ 42638712Smsmith struct module_metadata *md; 42738712Smsmith 42838712Smsmith for (md = mp->m_metadata; md != NULL; md = md->md_next) 42938712Smsmith if (md->md_type == type) 43038712Smsmith break; 43138712Smsmith return(md); 43238712Smsmith} 43338764Smsmith 43438764Smsmith/* 43539178Smsmith * Attempt to find the file (name) on the module searchpath. 43638764Smsmith * If (name) is qualified in any way, we simply check it and 43738764Smsmith * return it or NULL. If it is not qualified, then we attempt 43838764Smsmith * to construct a path using entries in the environment variable 43938764Smsmith * module_path. 44038764Smsmith * 44138764Smsmith * The path we return a pointer to need never be freed, as we manage 44238764Smsmith * it internally. 44338764Smsmith */ 44438764Smsmithstatic char * 44539178Smsmithmod_searchfile(char *name) 44638764Smsmith{ 44744570Sdcs char *result; 44839673Sdfr char *path, *sp; 44939673Sdfr const char *cp; 45038764Smsmith struct stat sb; 45138764Smsmith 45238764Smsmith /* Don't look for nothing */ 45344210Sdcs if (name == NULL) 45438764Smsmith return(name); 45538764Smsmith 45644210Sdcs if (*name == 0) 45744210Sdcs return(strdup(name)); 45844210Sdcs 45938764Smsmith /* 46038764Smsmith * See if there's a device on the front, or a directory name. 46138764Smsmith */ 46238764Smsmith archsw.arch_getdev(NULL, name, &cp); 46338764Smsmith if ((cp != name) || (strchr(name, '/') != NULL)) { 46438764Smsmith /* Qualified, so just see if it exists */ 46538764Smsmith if (stat(name, &sb) == 0) 46644210Sdcs return(strdup(name)); 46738764Smsmith return(NULL); 46838764Smsmith } 46938764Smsmith 47038764Smsmith /* 47138764Smsmith * Get the module path 47238764Smsmith */ 47338764Smsmith if ((cp = getenv("module_path")) == NULL) 47439178Smsmith cp = default_searchpath; 47538764Smsmith sp = path = strdup(cp); 47638764Smsmith 47738764Smsmith /* 47838764Smsmith * Traverse the path, splitting off ';'-delimited components. 47938764Smsmith */ 48044570Sdcs result = NULL; 48138764Smsmith while((cp = strsep(&path, ";")) != NULL) { 48239178Smsmith result = malloc(strlen(cp) + strlen(name) + 5); 48339178Smsmith strcpy(result, cp); 48439178Smsmith if (cp[strlen(cp) - 1] != '/') 48539178Smsmith strcat(result, "/"); 48639178Smsmith strcat(result, name); 48739178Smsmith/* printf("search '%s'\n", result); */ 48839178Smsmith if ((stat(result, &sb) == 0) && 48939178Smsmith S_ISREG(sb.st_mode)) 49038764Smsmith break; 49138764Smsmith free(result); 49238764Smsmith result = NULL; 49338764Smsmith } 49438764Smsmith free(sp); 49538764Smsmith return(result); 49638764Smsmith} 49738764Smsmith 49838764Smsmith/* 49939178Smsmith * Attempt to locate the file containing the module (name) 50039178Smsmith */ 50139178Smsmithstatic char * 50239178Smsmithmod_searchmodule(char *name) 50339178Smsmith{ 50439178Smsmith char *tn, *result; 50539178Smsmith 50639178Smsmith /* Look for (name).ko */ 50739673Sdfr tn = malloc(strlen(name) + 3 + 1); 50839178Smsmith strcpy(tn, name); 50939178Smsmith strcat(tn, ".ko"); 51039178Smsmith result = mod_searchfile(tn); 51139178Smsmith free(tn); 51239178Smsmith /* Look for just (name) (useful for finding kernels) */ 51339178Smsmith if (result == NULL) 51439178Smsmith result = mod_searchfile(name); 51539178Smsmith 51639178Smsmith return(result); 51739178Smsmith} 51839178Smsmith 51939178Smsmith 52039178Smsmith/* 52138764Smsmith * Throw a module away 52238764Smsmith */ 52338764Smsmithvoid 52438764Smsmithmod_discard(struct loaded_module *mp) 52538764Smsmith{ 52638764Smsmith struct module_metadata *md; 52738764Smsmith 52839178Smsmith if (mp != NULL) { 52939178Smsmith while (mp->m_metadata != NULL) { 53039178Smsmith md = mp->m_metadata; 53139178Smsmith mp->m_metadata = mp->m_metadata->md_next; 53239178Smsmith free(md); 53339178Smsmith } 53439178Smsmith if (mp->m_name != NULL) 53539178Smsmith free(mp->m_name); 53639178Smsmith if (mp->m_type != NULL) 53739178Smsmith free(mp->m_type); 53839178Smsmith if (mp->m_args != NULL) 53939178Smsmith free(mp->m_args); 54039178Smsmith free(mp); 54139178Smsmith } 54238764Smsmith} 54338764Smsmith 54438764Smsmith/* 54539178Smsmith * Allocate a new module; must be used instead of malloc() 54639178Smsmith * to ensure safe initialisation. 54739178Smsmith */ 54839178Smsmithstruct loaded_module * 54939178Smsmithmod_allocmodule(void) 55039178Smsmith{ 55139178Smsmith struct loaded_module *mp; 55239178Smsmith 55339178Smsmith if ((mp = malloc(sizeof(struct loaded_module))) != NULL) { 55439178Smsmith bzero(mp, sizeof(struct loaded_module)); 55539178Smsmith } 55639178Smsmith return(mp); 55739178Smsmith} 55839178Smsmith 55939178Smsmith 56039178Smsmith/* 56138764Smsmith * Add a module to the chain 56238764Smsmith */ 56338764Smsmithstatic void 56438764Smsmithmod_append(struct loaded_module *mp) 56538764Smsmith{ 56638764Smsmith struct loaded_module *cm; 56738764Smsmith 56838764Smsmith /* Append to list of loaded modules */ 56938764Smsmith mp->m_next = NULL; 57038764Smsmith if (loaded_modules == NULL) { 57138764Smsmith loaded_modules = mp; 57238764Smsmith } else { 57338764Smsmith for (cm = loaded_modules; cm->m_next != NULL; cm = cm->m_next) 57438764Smsmith ; 57538764Smsmith cm->m_next = mp; 57638764Smsmith } 57738764Smsmith} 578