diff -Naur busybox.orig/include/applets.h busybox/include/applets.h
--- busybox.orig/include/applets.h	2008-06-28 12:58:39 +0000
+++ busybox/include/applets.h	2008-06-30 20:06:52 +0000
@@ -116,6 +116,7 @@
 USE_DELGROUP(APPLET_ODDNAME(delgroup, deluser, _BB_DIR_BIN, _BB_SUID_NEVER, delgroup))
 USE_DELUSER(APPLET(deluser, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_DEPMOD(APPLET(depmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MODPROBE_NG(APPLET_ODDNAME(depmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe))
 USE_DEVFSD(APPLET(devfsd, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_DF(APPLET(df, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_APP_DHCPRELAY(APPLET(dhcprelay, _BB_DIR_USR_SBIN, _BB_SUID_NEVER))
@@ -188,6 +189,7 @@
 USE_INIT(APPLET(init, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_INOTIFYD(APPLET(inotifyd, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_INSMOD(APPLET(insmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MODPROBE_NG(APPLET_ODDNAME(insmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe))
 USE_INSTALL(APPLET(install, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
 #if ENABLE_FEATURE_IP_ADDRESS \
  || ENABLE_FEATURE_IP_ROUTE \
@@ -231,6 +233,7 @@
 USE_LS(APPLET_NOEXEC(ls, ls, _BB_DIR_BIN, _BB_SUID_NEVER, ls))
 USE_LSATTR(APPLET(lsattr, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_LSMOD(APPLET(lsmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MODPROBE_NG(APPLET_ODDNAME(lsmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe))
 USE_UNLZMA(APPLET_ODDNAME(lzmacat, unlzma, _BB_DIR_USR_BIN, _BB_SUID_NEVER, lzmacat))
 USE_MAKEDEVS(APPLET(makedevs, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_MAN(APPLET(man, _BB_DIR_SBIN, _BB_SUID_NEVER))
@@ -249,6 +252,7 @@
 USE_MKSWAP(APPLET(mkswap, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_MKTEMP(APPLET(mktemp, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_MODPROBE(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MODPROBE_NG(APPLET(modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_MORE(APPLET(more, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_MOUNT(APPLET(mount, _BB_DIR_BIN, USE_DESKTOP(_BB_SUID_MAYBE) SKIP_DESKTOP(_BB_SUID_NEVER)))
 USE_MOUNTPOINT(APPLET(mountpoint, _BB_DIR_BIN, _BB_SUID_NEVER))
@@ -293,6 +297,7 @@
 USE_RM(APPLET_NOFORK(rm, rm, _BB_DIR_BIN, _BB_SUID_NEVER, rm))
 USE_RMDIR(APPLET_NOFORK(rmdir, rmdir, _BB_DIR_BIN, _BB_SUID_NEVER, rmdir))
 USE_RMMOD(APPLET(rmmod, _BB_DIR_SBIN, _BB_SUID_NEVER))
+USE_MODPROBE_NG(APPLET_ODDNAME(rmmod, modprobe, _BB_DIR_SBIN, _BB_SUID_NEVER, modprobe))
 USE_ROUTE(APPLET(route, _BB_DIR_SBIN, _BB_SUID_NEVER))
 USE_RPM(APPLET(rpm, _BB_DIR_BIN, _BB_SUID_NEVER))
 USE_RPM2CPIO(APPLET(rpm2cpio, _BB_DIR_USR_BIN, _BB_SUID_NEVER))
diff -Naur busybox.orig/modutils/Config.in busybox/modutils/Config.in
--- busybox.orig/modutils/Config.in	2008-06-27 21:04:02 +0000
+++ busybox/modutils/Config.in	2008-06-30 20:55:22 +0000
@@ -5,9 +5,39 @@
 
 menu "Linux Module Utilities"
 
+config MODPROBE_NG
+	bool "Simplified modutils"
+	default n
+	help
+	  New format modutils. Compatible.
+
+config FEATURE_MODPROBE_NG_OPTIONS_ON_CMDLINE
+	bool "module options on cmdline"
+	default n
+	depends on MODPROBE_NG
+	help
+	  Allow insmod and modprobe take module options from command line.
+	  N.B. Very bloaty.
+
+config FEATURE_MODPROBE_NG_CHECK_ALREADY_LOADED
+	bool "skip loading of already loaded modules"
+	default n
+	depends on MODPROBE_NG
+	help
+	  Check if the module is already loaded.
+	  N.B. Racy. Slow. Bloaty.
+
+config FEATURE_MODPROBE_NG_ZIPPED
+	bool "handle gzipped or bzipped modules"
+	default n
+	depends on MODPROBE_NG
+	help
+	  Handle compressed modules. Bloaty. Sloooow.
+
 config DEPMOD
 	bool "depmod"
 	default n
+	depends on !MODPROBE_NG
 	help
 	  depmod generates modules.dep (FIXME: elaborate)
 
@@ -38,6 +68,7 @@
 config INSMOD
 	bool "insmod"
 	default n
+	depends on !MODPROBE_NG
 	help
 	  insmod is used to load specified modules in the running kernel.
 
@@ -93,12 +124,14 @@
 config RMMOD
 	bool "rmmod"
 	default n
+	depends on !MODPROBE_NG
 	help
 	  rmmod is used to unload specified modules from the kernel.
 
 config LSMOD
 	bool "lsmod"
 	default n
+	depends on !MODPROBE_NG
 	help
 	  lsmod is used to display a list of loaded modules.
 
@@ -113,6 +146,7 @@
 config MODPROBE
 	bool "modprobe"
 	default n
+	depends on !MODPROBE_NG
 	help
 	  Handle the loading of modules, and their dependencies on a high
 	  level.
@@ -196,7 +230,7 @@
 	# Simulate indentation
 	string "Default directory containing modules"
 	default "/lib/modules"
-	depends on INSMOD || RMMOD || MODPROBE || DEPMOD
+	depends on INSMOD || RMMOD || MODPROBE || MODPROBE_NG || DEPMOD
 	help
 	  Directory that contains kernel modules.
 	  Defaults to "/lib/modules"
@@ -205,7 +239,7 @@
 	# Simulate indentation
 	string "Default name of modules.dep"
 	default "modules.dep"
-	depends on INSMOD || RMMOD || MODPROBE || DEPMOD
+	depends on INSMOD || RMMOD || MODPROBE || MODPROBE_NG || DEPMOD
 	help
 	  Filename that contains kernel modules dependencies.
 	  Defaults to "modules.dep"
diff -Naur busybox.orig/modutils/Kbuild busybox/modutils/Kbuild
--- busybox.orig/modutils/Kbuild	2008-06-27 21:04:02 +0000
+++ busybox/modutils/Kbuild	2008-06-30 20:06:52 +0000
@@ -9,4 +9,5 @@
 lib-$(CONFIG_INSMOD)		+= insmod.o
 lib-$(CONFIG_LSMOD)		+= lsmod.o
 lib-$(CONFIG_MODPROBE)		+= modprobe.o
+lib-$(CONFIG_MODPROBE_NG)	+= modprobe-ng.o
 lib-$(CONFIG_RMMOD)		+= rmmod.o
diff -Naur busybox.orig/modutils/modprobe-ng.c busybox/modutils/modprobe-ng.c
--- busybox.orig/modutils/modprobe-ng.c	1970-01-01 00:00:00 +0000
+++ busybox/modutils/modprobe-ng.c	2008-06-30 21:11:04 +0000
@@ -0,0 +1,581 @@
+/* vi: set sw=4 ts=4: */
+/*
+ * simplified depmod & modprobe
+ *
+ * Copyright (c) 2008 Vladimir Dronnikov
+ * Copyright (c) 2008 Bernhard Fischer (initial depmod code)
+ *
+ * Licensed under GPLv2, see file LICENSE in this tarball for details.
+ */
+
+#include "libbb.h"
+#include "unarchive.h"
+
+#include <sys/utsname.h> /* uname() */
+#include <fnmatch.h>
+
+extern int init_module(void *module, unsigned long len, const char *options);
+extern int delete_module(const char *module, unsigned flags);
+extern int query_module(const char *name, int which, void *buf, size_t bufsize, size_t *ret);
+
+enum {
+	OPT_q = (1 << 0), /* be quiet */
+	OPT_r = (1 << 1), /* module removal instead of loading */
+};
+
+/*
+ * GLOBALS
+ */
+struct globals {
+	char *modules_dep;
+	char *modules_dep_ptr;
+};
+#define G (*ptr_to_globals)
+#define modules_dep	(G.modules_dep)
+#define modules_dep_ptr	(G.modules_dep_ptr)
+#define INIT_G() do { \
+	SET_PTR_TO_GLOBALS(xzalloc(sizeof(G))); \
+} while (0)
+
+static void appendc(char c)
+{
+	*modules_dep_ptr++ = c;
+}
+
+static void append(const char *s)
+{
+	size_t len = strlen(s);
+	memcpy(modules_dep_ptr, s, len);
+	modules_dep_ptr += len;
+}
+
+static char* find_keyword(char *ptr, size_t len, const char *word)
+{
+	int wlen = strlen(word);
+
+	len -= wlen - 1;
+	while ((ssize_t)len > 0) {
+		char *old = ptr;
+		/* search for the first char in word */
+		ptr = memchr(ptr, *word, len);
+		if (ptr == NULL) /* no occurance left, done */
+			break;
+		if (strncmp(ptr, word, wlen) == 0)
+			return ptr + wlen; /* found, return ptr past it */
+		++ptr;
+		len -= (ptr - old);
+	}
+	return NULL;
+}
+
+static void replace(char *s, char what, char with)
+{
+	while (*s) {
+		if (what == *s)
+			*s = with;
+		++s;
+	}
+}
+
+/* libbb candidate */
+static void *xmalloc_read(int fd, size_t *sizep)
+{
+	char *buf;
+	size_t size, rd_size, total;
+	off_t to_read;
+	struct stat st;
+
+	to_read = sizep ? *sizep : INT_MAX; /* max to read */
+
+	/* Estimate file size */
+	st.st_size = 0; /* in case fstat fails, assume 0 */
+	fstat(fd, &st);
+	/* /proc/N/stat files report st_size 0 */
+	/* In order to make such files readable, we add small const */
+	size = (st.st_size | 0x3ff) + 1;
+
+	total = 0;
+	buf = NULL;
+	while (1) {
+		if (to_read < size)
+			size = to_read;
+		buf = xrealloc(buf, total + size + 1);
+		rd_size = full_read(fd, buf + total, size);
+		if ((ssize_t)rd_size < 0) { /* error */
+			free(buf);
+			return NULL;
+		}
+		total += rd_size;
+		if (rd_size < size) /* EOF */
+			break;
+		to_read -= rd_size;
+		if (to_read <= 0)
+			break;
+		/* grow by 1/8, but in [1k..64k] bounds */
+		size = ((total / 8) | 0x3ff) + 1;
+		if (size > 64*1024)
+			size = 64*1024;
+	}
+	xrealloc(buf, total + 1);
+	buf[total] = '\0';
+
+	if (sizep)
+		*sizep = total;
+	return buf;
+}
+
+#if ENABLE_FEATURE_MODPROBE_NG_ZIPPED
+static FAST_FUNC char *xmalloc_open_zipped_read_close(const char *fname, size_t *sizep)
+{
+	size_t len;
+	char *image;
+	char *suffix = strrchr(fname, '.');
+
+	int fd = open_or_warn(fname, O_RDONLY);
+	if (fd < 0)
+		return NULL;
+
+	if (suffix) {
+		if (strcmp(suffix, ".gz") == 0)
+			fd = open_transformer(fd, unpack_gz_stream, "gunzip");
+		else if (strcmp(suffix, ".bz2") == 0)
+			fd = open_transformer(fd, unpack_bz2_stream, "bunzip2");
+	}
+
+	len = (sizep) ? *sizep : 64 * 1024 * 1024;
+	image = xmalloc_read(fd, &len);
+	if (!image)
+		bb_perror_msg("read");
+	close(fd);
+
+	if (sizep)
+		*sizep = len;
+	return image;
+}
+#	define load xmalloc_open_zipped_read_close
+#else
+#	define load xmalloc_open_read_close
+#endif
+
+static FAST_FUNC int fileAction(const char *fname,
+		struct stat *sb ATTRIBUTE_UNUSED,
+		void *data ATTRIBUTE_UNUSED,
+		int depth ATTRIBUTE_UNUSED)
+{
+	char *module_image;
+	char *ptr;
+	char *name;
+	const char *suffix;
+	size_t pos;
+	size_t len;
+
+	fname += 2; /* skip "./" */
+
+	suffix = strrstr(fname, ".ko");
+	if (!suffix) /* not a module */
+		return TRUE;
+
+	/* Load (possibly compressed) module */
+	len = 64 * 1024 * 1024; // 64 Mb at most
+	module_image = load(fname, &len);
+
+	name = xstrdup(bb_get_last_path_component_nostrip(fname));
+	ptr = strrstr(name, ".ko");
+	*ptr = '\0';
+	replace(name, '-', '_');
+
+	// module name ...
+	append(name);
+	appendc(' ');
+
+	// ... and aliases
+	pos = 0;
+	while (1) {
+		ptr = find_keyword(module_image + pos, len - pos, "alias=");
+		if (!ptr) {
+			ptr = find_keyword(module_image + pos, len - pos, "__ksymtab_");
+			if (!ptr)
+				break;
+		}
+		// FIXME: __ksymtab_gpl and __ksymtab_strings occur in many modules.
+		// What do they mean?!
+		append(('_' == ptr[-1]) ? "symbol:" : "");
+		append(ptr);
+		appendc(' ');
+		pos = (ptr - module_image);
+	}
+	appendc('\0');
+
+	// dependencies
+	ptr = find_keyword(module_image, len, "depends=");
+	if (ptr && *ptr) {
+		replace(ptr, ',', ' ');
+		replace(ptr, '-', '_');
+		append(ptr);
+	}
+	appendc(' '); appendc('\0');
+
+	// filename
+	append(fname); appendc('\0');
+
+	free(name);
+	free(module_image);
+	return TRUE;
+}
+
+#if ENABLE_FEATURE_MODPROBE_NG_CHECK_ALREADY_LOADED
+
+//
+// do not try to load module which is already loaded
+//
+
+// 2.4 kernels only
+static int already_loaded_24(const char *name)
+{
+	struct module_info {
+		unsigned long addr;
+		unsigned long size;
+		unsigned long flags;
+		long usecount;
+	} info;
+	size_t dummy;
+	return !query_module(name, 5 /*QM_INFO*/, &info, sizeof(info), &dummy);
+}
+
+// 2.6 kernels only
+static int already_loaded_26(const char *name)
+{
+	char *fname = xasprintf("/sys/module/%s", name);
+	struct stat st;
+	int ret = !lstat(fname, &st);
+	free(fname);
+	return ret;
+}
+
+// any kernel but works iff `wc /proc/modules` < 1024
+static int already_loaded_1024(const char *name)
+{
+	int ret = 0;
+	int len = strlen(name);
+
+	char *modules = xmalloc_open_read_close("/proc/modules", NULL);
+	if (modules) {
+		for (char *s = modules; (s = strstr(s, name)); s += len) {
+			if (' ' == s[len] && (s == s || '\n' == s[-1])) {
+				++ret;
+				break;
+			}
+		}
+	}
+
+	return ret;
+}
+
+// any kernel but assuming `wc /proc/modules` < BB_COMMON_BUFSIZ
+// N.B. So what?! We do not fail on false positive/negative.
+// So let it be heuristics!
+static int already_loaded_4096(const char *name)
+{
+
+// FIXME: overflow?
+#define modules bb_common_bufsiz1
+
+	int ret = 0;
+	int len = strlen(name);
+	// N.B. can't use mmap or xmalloc_open_read_close()! They report wrong file length on mem-backed /proc/modules!!!
+	if (open_read_close("/proc/modules", modules, sizeof(modules)) >= 0) {
+		for (char *s = modules; (s = strstr(s, name)); s += len) {
+			if (' ' == s[len] && (s == s || '\n' == s[-1])) {
+				++ret;
+				break;
+			}
+		}
+	}
+
+#undef modules
+
+	return ret;
+}
+
+// any kernel but bloaty
+static int already_loaded_0(const char *name)
+{
+	int ret = 0;
+	int len = strlen(name);
+
+	FILE *fp = fopen("/proc/modules", "r");
+	if (fp) {
+		char *s;
+		while ((s = xmalloc_fgets_str(fp, "\n"))) {
+			if (' ' == s[len] && 0 == strncmp(s, name, len)) {
+				free(s);
+				++ret;
+				break;
+			}
+			free(s);
+		}
+		fclose(fp);
+	}
+
+	return ret;
+}
+
+#define already_loaded already_loaded_26
+
+#else
+static int already_loaded(const char ATTRIBUTE_UNUSED *name)
+{
+	return 0;
+}
+#endif
+
+/* We use error numbers in a loose translation... */
+static const char *moderror(int err)
+{
+	switch (err) {
+	case ENOEXEC:
+		return "invalid module format";
+	case ENOENT:
+		return "unknown symbol in module";
+	case ESRCH:
+		return "module has wrong symbol version";
+	case EINVAL:
+		return "invalid parameters";
+	default:
+		return strerror(err);
+	}
+}
+
+static void load_module(const char *fname, const char *options)
+{
+	size_t len = MAXINT(ssize_t);
+
+	char *module_image = load(fname, &len);
+
+	errno = 0;
+	if (!module_image || init_module(module_image, len, options ? options : "") != 0)
+		if (EEXIST != errno)
+			bb_error_msg("insert '%s' %s: %s",
+					fname, options, moderror(errno));
+
+	free(module_image);
+}
+
+/*
+ Given modules definition and module name (or alias, or symbol)
+ load/remove the module respecting dependencies
+*/
+#if !ENABLE_FEATURE_MODPROBE_NG_OPTIONS_ON_CMDLINE
+#define process_module(a,b) process_module(a)
+#define cmdline_options ""
+#endif
+static void process_module(char *name, const char *cmdline_options)
+{
+	// read definitions
+	const char *ptr = modules_dep;
+	char *s, *deps;
+	int i;
+
+	replace(name, '-', '_');
+
+	// iterate thru definitions
+	while (*ptr) {
+		// matching substring exists?
+		deps = xstrdup(ptr);
+		replace(deps, ' ', '\0');
+		for (s = deps; *s; s += strlen(s) + 1) {
+			if (!fnmatch(s, name, 0)) {
+				free(deps);
+				goto found;
+			}
+		}
+		free(deps);
+		// ... skip to next module definition
+		for (i = 3; --i >= 0; )
+			ptr += strlen(ptr) + 1;
+	}
+	// no module matched -> try to load module from specified filename
+	// N.B. this mimics insmod behaviour
+	load_module(name, cmdline_options);
+	return;
+
+	// module matched
+ found:
+	// yes -> found module definition! replace possible aliased name with module general name
+	name = xstrdup(ptr);
+	*strchrnul(name, ' ') = '\0';
+
+	// on rmmod unload it by name
+	if (option_mask32 & OPT_r) {
+		if (delete_module(name, O_NONBLOCK|O_EXCL) && !(option_mask32 & OPT_q))
+			bb_perror_msg("remove '%s'", name);
+		// N.B. And continue to unload modules on which the module depends.
+		// That way we implement auto-clean feature
+	}
+
+	// next line contains dependencies
+	ptr += strlen(ptr) + 1;
+	// copy dependencies string
+	deps = xstrdup(ptr);
+	// transform it to string list
+	replace(deps, ' ', '\0');
+	// iterate thru dependencies, trying to load them
+	for (s = deps; *s; s += strlen(s) + 1) {
+		//if (strcmp(name, s) != 0) // N.B. Do loops ever exist?!
+			process_module(s, cmdline_options);
+	}
+	free(deps);
+
+	// next line contains full path and optionally :) options
+	ptr += strlen(ptr) + 1;
+
+	// on insmod if module is not loaded -> load it by filename
+	if (!(option_mask32 & OPT_r) && !already_loaded(name)) {
+		// fetch parameters (if any)
+		char *opt_filename = xasprintf("/etc/modules/%s", name);
+		char *options = xmalloc_open_read_close(opt_filename, NULL);
+		// patch parameters: remove EOLs
+		if (options)
+			replace(options, '\n', ' ');
+		// do load
+#if ENABLE_FEATURE_MODPROBE_NG_OPTIONS_ON_CMDLINE
+		if (cmdline_options) {
+			char *op = xasprintf("%s %s", cmdline_options, options);
+			load_module(ptr, op);
+			free(op);
+		} else
+#endif
+			load_module(ptr, options);
+		// cleanup
+		free(options);
+		free(opt_filename);
+	}
+
+	// cleanup
+	free(name);
+}
+#undef cmdline_options
+
+/* For reference, module-init-tools-0.9.15-pre2 options:
+
+# insmod
+Usage: insmod filename [args]
+
+# rmmod --help
+Usage: rmmod [-fhswvV] modulename ...
+ -f (or --force) forces a module unload, and may crash your machine.
+ -s (or --syslog) says use syslog, not stderr
+ -v (or --verbose) enables more messages
+ -w (or --wait) begins a module removal even if it is used
+    and will stop new users from accessing the module (so it
+    should eventually fall to zero).
+
+# modprobe
+Usage: modprobe [--verbose|--version|--config|--remove] filename options
+
+# depmod --help
+depmod 0.9.15-pre2 -- part of module-init-tools
+depmod -[aA] [-n -e -v -q -V -r -u] [-b basedirectory] [forced_version]
+depmod [-n -e -v -q -r -u] [-F kernelsyms] module1.o module2.o ...
+If no arguments (except options) are given, "depmod -a" is assumed
+
+depmod will output a dependancy list suitable for the modprobe utility.
+
+Options:
+        -a, --all               Probe all modules
+        -n, --show              Write the dependency file on stdout only
+        -b basedirectory
+        --basedir basedirectory Use an image of a module tree.
+        -F kernelsyms
+        --filesyms kernelsyms   Use the file instead of the
+                                current kernel symbols.
+*/
+
+// FIXME: code size matters?
+#define _SMALLER_BUT_UGLIER__WHAT_DO_WE_CHOOSE_
+
+int modprobe_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
+int modprobe_main(int ATTRIBUTE_UNUSED argc, char **argv)
+{
+#ifdef _SMALLER_BUT_UGLIER__WHAT_DO_WE_CHOOSE_
+#	define uts bb_common_bufsiz1
+#else
+	struct utsname uts;
+#endif
+	char *options;
+
+	// are we lsmod? -> just dump /proc/modules
+	if ('l' == applet_name[0]) {
+		xprint_and_close_file(xfopen("/proc/modules", "r"));
+		return EXIT_SUCCESS;
+	}
+
+	// depmod is a stub
+	if ('d' == applet_name[0])
+		return EXIT_SUCCESS;
+
+	// insmod, modprobe, rmmod require at least one argument
+	opt_complementary = "-1";
+	// only -q (quiet) and -r (rmmod),
+	// the rest are accepted and ignored (compat)
+	getopt32(argv, "qrfsvw");
+	argv += optind;
+
+	// are we rmmod? -> simulate modprobe -r
+	if ('r' == applet_name[0]) {
+		option_mask32 |= OPT_r;
+	}
+
+	// goto modules directory
+	xchdir(CONFIG_DEFAULT_MODULES_DIR);
+#ifdef _SMALLER_BUT_UGLIER__WHAT_DO_WE_CHOOSE_
+	if ((uname((struct utsname *)uts) >= 0)) {
+		xchdir(((struct utsname *)uts)->release);
+	}
+#else
+	if (uname(&uts) >= 0) {
+		xchdir(uts.release);
+	}
+#endif
+
+	// fetch definitions
+	// FIXME: overflow! Has BB extendable strings support?
+	INIT_G();
+	modules_dep = modules_dep_ptr = xzalloc(128 * 1024);
+	recursive_action(".",
+		ACTION_RECURSE, /* flags */
+		fileAction, /* file action */
+		NULL, /* dir action */
+		NULL, /* user data */
+		0); /* depth */
+
+	// If not rmmod, parse possible module options given on command line.
+	// insmod/modprobe takes one module name, the rest of argv are parameters.
+	// N.B. argv[0] cannot be NULL here.
+	options = NULL;
+	if (ENABLE_FEATURE_MODPROBE_NG_OPTIONS_ON_CMDLINE
+	 && !(option_mask32 & OPT_r)
+	) {
+		char **arg = argv;
+		while (*++arg) {
+			// enclose options in quotes
+			char *s = options;
+			options = xasprintf("%s\"%s\" ", s ? s : "", *arg);
+			free(s);
+			*arg = NULL;
+		}
+	}
+
+	// do load/remove modules
+	// only rmmod loops here, insmod/modprobe has only argv[0]
+	do {
+		process_module(*argv++, options);
+	} while (*argv);
+
+	// cleanup and exit
+	if (ENABLE_FEATURE_CLEAN_UP) {
+		free(modules_dep);
+		free(options);
+	}
+	return EXIT_SUCCESS;
+}
