[klibc] klibc insmod for recent kernels

H. Peter Anvin hpa@zytor.com
Fri, 03 Jan 2003 23:02:47 -0800


Rusty Russell wrote:
>>
>>Not a good idea is probably a good way to sum it up, especially for 
>>system().  Why on earth does module-init-tools need system()?  Requiring 
>>a shell to install modules seems, ahem, daft?
> 
> No.  You can insert arbitary commands in the /etc/modprobe.conf (as
> you could in /etc/modules.conf), which it executes in place of
> inserting the module.

Sure, but why spawn /bin/sh to do it?  It seems doing it internally 
would be both cleaner and faster.

> Do you want a config file at all for this?  Probably not.  Something
> simple like the following (untested, but you get the idea) is probably
> what you want.  Adjust to suit... this would be easier in a scripting
> language, of course.

Probably not, in this application.  The kind of things you have below is 
more like it.  (klibc doesn't use syscall(nr, ...) -- you just name the 
syscall; if it conflicts with a C library function with different 
semantics add __ in front.)

	-hpa


> /* Dumb as dust modprobe.  Usage: modprobe modulename modules.dep */
> static void *read_in(const char *filename, unsigned long *len)
> {
> 	void *ret;
> 	unsigned long done = 0;
> 	int r, fd;
> 	struct stat statbuf;
> 
> 	fd = open(filename, O_RDONLY);
> 	if (fstat(fd, &statbuf) < 0)
> 		exit(1);
> 	*len = statbuf.st_size;
> 	ret = malloc(*len + 1);
> 	
> 	while (done < *len) {
> 		r = read(fd, ret + done, *len - done);
> 		if (r <= 0)
> 			exit(1);
> 		done += r;
> 	}
> 	ret[*len] = '\0';
> 	return ret;
> }
> 
> /* Insert in reverse order. */
> static void insmod(const char *files)
> {
> 	char *sep, *module;
> 	unsigned long len;
> 
> 	if (!files)
> 		return;
> 
> 	/* Swallow leading spaces */
> 	while (files[0] == ' ')
> 		files++;
> 	
> 	sep = strchr(files, ' ');
> 	insmod(sep);
> 	*sep = '\0';
> 
> 	module = read_in(files, &len);
> 	if (syscall(__NR_init_module, module, len, "") != 0)
> 		exit(1);
> 	free(module);
> }
> 
> int main(int argc, char *argv[])
> {
> 	char *deps, *ptr;
> 	unsigned long len;
> 	
> 	deps = read_in(argv[2], &len);
> 
> 	for (ptr = strstr(deps, argv[1]); ptr; ptr = strstr(ptr+1, argv[1])) {
> 		if (ptr != deps && ptr[-1] != '/' && ptr[-1] != '\n')
> 			continue;
> 		if (ptr[strlen(argv[1])] != ':')
> 			continue;
> 		break;
> 	}
> 	if (!ptr)
> 		exit(1);
> 
> 	/* Turn into one-line list of modules. */
> 	*strchr(ptr, ':') = ' ';
> 	deps = ptr;
> 	ptr = strchr(deps, '\n');
> 	if (ptr)
> 		*ptr = '\0';
> 	insmod(deps);
> }
> --
>   Anyone who quotes me in their sig is an idiot. -- Rusty Russell.