#ifndef lint
static const char rcsid[] =
"$Id: kmodunload.c,v 1.3 2001/02/05 19:53:16 lindak Exp $";
#endif
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <mach/mach.h>
#include <mach/mach_error.h>
#include <mach/mach_host.h>
static int verbose = 0;
#define v_printf if (verbose) printf
static void
machwarn(int error, const char *message)
{
if (error == KERN_SUCCESS) return;
fprintf(stderr, "kmodunload: %s: %s\n", message, mach_error_string(error));
}
static void
macherr(int error, const char *message)
{
if (error == KERN_SUCCESS) return;
fprintf(stderr, "kmodunload: %s: %s\n", message, mach_error_string(error));
exit(1);
}
static mach_port_t kernel_priv_port;
static void
stop_module(kmod_t id)
{
int r;
void * args = 0;
int argsCount= 0;
r = kmod_control(kernel_priv_port, id, KMOD_CNTL_STOP, &args, &argsCount);
macherr(r, "kmod_control(stop) failed");
v_printf("kmodunload: kmod id %d successfully stopped.\n", id);
}
static void
unload_module(kmod_t id)
{
int r;
r = kmod_destroy(kernel_priv_port, id);
macherr(r, "kmod_destroy() failed");
v_printf("kmodunload: kmod id %d successfully unloaded.\n", id);
}
static void
usage(void)
{
fprintf(stderr, "usage: kmodunload [-v] -i id\n");
fprintf(stderr, " kmodunload [-v] -n name\n");
exit(1);
}
int
main(int argc, char** argv)
{
int c;
int id = 0;
char* name = 0;
kmod_info_t *info;
int r;
int count;
mach_port_t kernel_port;
while ((c = getopt(argc, argv, "i:n:v")) != -1)
switch (c) {
case 'i':
id = atoi(optarg);
break;
case 'n':
name = optarg;
break;
case 'v':
verbose = 1;
break;
default:
usage();
}
argc -= optind;
argv += optind;
if (!id && !name && (argc == 1)) {
name = *argv;
argc--;
}
if ((argc != 0) || (id && name))
usage();
if ((id == 0) && (name == 0))
usage();
r = task_for_pid(mach_task_self(), 0, &kernel_port);
machwarn(r, "unable to get kernel task port");
if (r) {
fprintf(stderr, "kmodunload: Are you running as root?\n");
exit(1);
}
r = kmod_get_info(kernel_port, (void *)&info, &count);
macherr(r, "kmod_get_info() failed");
if (count < 1) {
fprintf(stderr, "kmodunload: there is nothing to unload?\n");
exit(1);
}
if (name) {
kmod_info_t *k = info;
while (k) {
if (!strcmp(k->name, name)) {
id = k->id;
break;
}
k = (k->next) ? (k + 1) : 0;
}
if (!k) {
fprintf(stderr, "kmodunload: can't kmod named: %s.\n", name);
exit(1);
}
} else {
kmod_info_t *k = info;
while (k) {
if (id == k->id) {
name = k->name;
break;
}
k = (k->next) ? (k + 1) : 0;
}
if (!name) {
fprintf(stderr, "kmodunload: can't find kmod id %d.\n", id);
exit(1);
}
}
v_printf("kmodunload: found kmod %s, id %d.\n", name, id);
kernel_priv_port = mach_host_self();
stop_module(id);
unload_module(id);
return 0;
}