125540Sdfr/*-
225540Sdfr * Copyright (c) 1997 Doug Rabson
325540Sdfr * All rights reserved.
425540Sdfr *
525540Sdfr * Redistribution and use in source and binary forms, with or without
625540Sdfr * modification, are permitted provided that the following conditions
725540Sdfr * are met:
825540Sdfr * 1. Redistributions of source code must retain the above copyright
925540Sdfr *    notice, this list of conditions and the following disclaimer.
1025540Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1125540Sdfr *    notice, this list of conditions and the following disclaimer in the
1225540Sdfr *    documentation and/or other materials provided with the distribution.
1325540Sdfr *
1425540Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1525540Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1625540Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1725540Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1825540Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1925540Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2025540Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2125540Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2225540Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2325540Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2425540Sdfr * SUCH DAMAGE.
2525540Sdfr */
2625540Sdfr
27114589Sobrien#include <sys/cdefs.h>
28114589Sobrien__FBSDID("$FreeBSD$");
2932270Scharnier
30156087Swkoszek#include <sys/param.h>
31156087Swkoszek#include <sys/linker.h>
32156087Swkoszek
3330573Sjmg#include <err.h>
3425540Sdfr#include <stdio.h>
3530573Sjmg#include <stdlib.h>
36156091Swkoszek#include <sysexits.h>
3725540Sdfr#include <unistd.h>
3825540Sdfr
3930627Sjmgstatic void
4030627Sjmgusage(void)
4125540Sdfr{
42156091Swkoszek	fprintf(stderr, "usage: kldunload [-fv] -i id ...\n");
43156091Swkoszek	fprintf(stderr, "       kldunload [-fv] [-n] name ...\n");
44156091Swkoszek	exit(EX_USAGE);
4525540Sdfr}
4625540Sdfr
47156091Swkoszek#define OPT_NULL	0x00
48156091Swkoszek#define OPT_ID		0x01
49156091Swkoszek#define OPT_VERBOSE	0x02
50156091Swkoszek#define OPT_FORCE	0x04
51156091Swkoszek
5230627Sjmgint
5330627Sjmgmain(int argc, char** argv)
5425540Sdfr{
55156087Swkoszek	struct kld_file_stat stat;
56156091Swkoszek	int c, fileid, force, opt;
57156091Swkoszek	char *filename;
5825540Sdfr
59156091Swkoszek	filename = NULL;
60156091Swkoszek	opt = OPT_NULL;
61156091Swkoszek
62156091Swkoszek	while ((c = getopt(argc, argv, "finv")) != -1) {
63156087Swkoszek		switch (c) {
64156087Swkoszek		case 'f':
65156091Swkoszek			opt |= OPT_FORCE;
66156087Swkoszek			break;
67156087Swkoszek		case 'i':
68156091Swkoszek			opt |= OPT_ID;
69156087Swkoszek			break;
70156087Swkoszek		case 'n':
71156091Swkoszek			/*
72156091Swkoszek			 * XXX: For backward compatibility. Currently does
73156091Swkoszek			 * nothing
74156091Swkoszek			 */
75156087Swkoszek			break;
76156087Swkoszek		case 'v':
77156091Swkoszek			opt |= OPT_VERBOSE;
78156087Swkoszek			break;
79156087Swkoszek		default:
80156087Swkoszek			usage();
81156087Swkoszek		}
8225540Sdfr	}
8325540Sdfr
84156087Swkoszek	argc -= optind;
85156087Swkoszek	argv += optind;
8625540Sdfr
87156091Swkoszek	if (argc == 0)
88156087Swkoszek		usage();
8925540Sdfr
90156091Swkoszek	while ((filename = *argv++) != NULL) {
91156091Swkoszek		if (opt & OPT_ID) {
92156091Swkoszek			fileid = atoi(filename);
93156091Swkoszek			if (fileid < 0)
94156091Swkoszek				errx(EXIT_FAILURE, "Invalid ID %s", optarg);
95156091Swkoszek		} else {
96156091Swkoszek			if ((fileid = kldfind(filename)) < 0)
97156091Swkoszek				errx(EXIT_FAILURE, "can't find file %s",
98156091Swkoszek				    filename);
99156091Swkoszek		}
100156091Swkoszek		if (opt & OPT_VERBOSE) {
101156091Swkoszek			stat.version = sizeof(stat);
102156091Swkoszek			if (kldstat(fileid, &stat) < 0)
103156091Swkoszek				err(EXIT_FAILURE, "can't stat file");
104156091Swkoszek			(void) printf("Unloading %s, id=%d\n", stat.name,
105156091Swkoszek			    fileid);
106156091Swkoszek		}
107156091Swkoszek		if (opt & OPT_FORCE)
108156091Swkoszek			force = LINKER_UNLOAD_FORCE;
109156091Swkoszek		else
110156091Swkoszek			force = LINKER_UNLOAD_NORMAL;
11125540Sdfr
112156091Swkoszek		if (kldunloadf(fileid, force) < 0)
113156091Swkoszek			err(EXIT_FAILURE, "can't unload file");
114156087Swkoszek	}
11525540Sdfr
116156091Swkoszek	return (EXIT_SUCCESS);
11725540Sdfr}
118