#include <sys/param.h>
#include <sys/linker.h>
#include <sys/stat.h>
#include <err.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
static void
check_path(const char *kldname, const struct kld_file_stat *kldst)
{
struct stat st1, st2;
if (strchr(kldname, '/') != NULL || strstr(kldname, ".ko") == NULL)
return;
if (stat(kldname, &st1) != 0)
return;
if (stat(kldst->pathname, &st2) != 0)
return;
if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
warnx("module %s was loaded from %s, not the current directory",
kldname, kldst->pathname);
}
static void
usage(void)
{
fprintf(stderr, "usage: kldload [-nv] file ...\n");
exit(1);
}
int
main(int argc, char **argv)
{
int c;
int errors;
int fileid;
int verbose;
int check_loaded;
struct kld_file_stat kldst;
errors = 0;
verbose = 0;
check_loaded = 0;
kldst.version = sizeof(struct kld_file_stat);
while ((c = getopt(argc, argv, "nv")) != -1)
switch (c) {
case 'n':
check_loaded = 1;
break;
case 'v':
verbose = 1;
break;
default:
usage();
}
argc -= optind;
argv += optind;
if (argc == 0)
usage();
while (argc-- != 0) {
fileid = kldload(argv[0]);
if (fileid < 0) {
if (check_loaded != 0 && errno == EEXIST) {
if (verbose)
printf("%s is already loaded\n", argv[0]);
} else {
switch (errno) {
case EEXIST:
warnx("can't load %s: module already loaded or "
"in kernel", argv[0]);
break;
case ENOEXEC:
warnx("an error occurred while loading module %s. "
"Please check dmesg(8) for more details.", argv[0]);
break;
default:
warn("can't load %s", argv[0]);
break;
}
errors++;
}
} else {
if (kldstat(fileid, &kldst) != 0)
warn("kldstat(id=%d)", fileid);
if (verbose)
printf("Loaded %s, id=%d, path=%s\n", argv[0], fileid,
kldst.pathname);
check_path(argv[0], &kldst);
}
argv++;
}
return errors ? 1 : 0;
}