Deleted Added
full compact
devctl.c (278320) devctl.c (298707)
1/*-
2 * Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 2014 John Baldwin <jhb@FreeBSD.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 *
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 * SUCH DAMAGE.
25 */
26
27#include <sys/cdefs.h>
28__FBSDID("$FreeBSD: head/usr.sbin/devctl/devctl.c 278320 2015-02-06 16:09:01Z jhb $");
28__FBSDID("$FreeBSD: head/usr.sbin/devctl/devctl.c 298707 2016-04-27 16:29:03Z jhb $");
29
30#include <sys/linker_set.h>
31#include <devctl.h>
32#include <err.h>
33#include <errno.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <strings.h>
38#include <unistd.h>
39
40struct devctl_command {
41 const char *name;
42 int (*handler)(int ac, char **av);
43};
44
45#define DEVCTL_DATASET(name) devctl_ ## name ## _table
46
47#define DEVCTL_COMMAND(set, name, function) \
48 static struct devctl_command function ## _devctl_command = \
49 { #name, function }; \
50 DATA_SET(DEVCTL_DATASET(set), function ## _devctl_command)
51
52#define DEVCTL_TABLE(set, name) \
53 SET_DECLARE(DEVCTL_DATASET(name), struct devctl_command); \
54 \
55 static int \
56 devctl_ ## name ## _table_handler(int ac, char **av) \
57 { \
58 return (devctl_table_handler(SET_BEGIN(DEVCTL_DATASET(name)), \
59 SET_LIMIT(DEVCTL_DATASET(name)), ac, av)); \
60 } \
61 DEVCTL_COMMAND(set, name, devctl_ ## name ## _table_handler)
62
63static int devctl_table_handler(struct devctl_command **start,
64 struct devctl_command **end, int ac, char **av);
65
66SET_DECLARE(DEVCTL_DATASET(top), struct devctl_command);
67
68DEVCTL_TABLE(top, set);
69
70static void
71usage(void)
72{
73 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
74 "usage: devctl attach device",
75 " devctl detach [-f] device",
76 " devctl disable [-f] device",
77 " devctl enable device",
78 " devctl suspend device",
79 " devctl resume device",
80 " devctl set driver [-f] device driver");
81 exit(1);
82}
83
84static int
85devctl_table_handler(struct devctl_command **start,
86 struct devctl_command **end, int ac, char **av)
87{
88 struct devctl_command **cmd;
89
90 if (ac < 2) {
91 warnx("The %s command requires a sub-command.", av[0]);
92 return (EINVAL);
93 }
94 for (cmd = start; cmd < end; cmd++) {
95 if (strcmp((*cmd)->name, av[1]) == 0)
96 return ((*cmd)->handler(ac - 1, av + 1));
97 }
98
99 warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
100 return (ENOENT);
101}
102
103static int
104help(int ac __unused, char **av __unused)
105{
106
107 usage();
108 return (0);
109}
110DEVCTL_COMMAND(top, help, help);
111
112static int
113attach(int ac, char **av)
114{
115
116 if (ac != 2)
117 usage();
118 if (devctl_attach(av[1]) < 0)
119 err(1, "Failed to attach %s", av[1]);
120 return (0);
121}
122DEVCTL_COMMAND(top, attach, attach);
123
124static void
125detach_usage(void)
126{
127
128 fprintf(stderr, "usage: devctl detach [-f] device\n");
129 exit(1);
130}
131
132static int
133detach(int ac, char **av)
134{
135 bool force;
136 int ch;
137
138 force = false;
139 while ((ch = getopt(ac, av, "f")) != -1)
140 switch (ch) {
141 case 'f':
142 force = true;
143 break;
144 default:
145 detach_usage();
146 }
147 ac -= optind;
148 av += optind;
149
150 if (ac != 1)
151 detach_usage();
152 if (devctl_detach(av[0], force) < 0)
153 err(1, "Failed to detach %s", av[0]);
154 return (0);
155}
156DEVCTL_COMMAND(top, detach, detach);
157
158static void
159disable_usage(void)
160{
161
162 fprintf(stderr, "usage: devctl disable [-f] device\n");
163 exit(1);
164}
165
166static int
167disable(int ac, char **av)
168{
169 bool force;
170 int ch;
171
172 force = false;
173 while ((ch = getopt(ac, av, "f")) != -1)
174 switch (ch) {
175 case 'f':
176 force = true;
177 break;
178 default:
179 disable_usage();
180 }
181 ac -= optind;
182 av += optind;
183
184 if (ac != 1)
185 disable_usage();
186 if (devctl_disable(av[0], force) < 0)
187 err(1, "Failed to disable %s", av[0]);
188 return (0);
189}
190DEVCTL_COMMAND(top, disable, disable);
191
192static int
193enable(int ac, char **av)
194{
195
196 if (ac != 2)
197 usage();
198 if (devctl_enable(av[1]) < 0)
199 err(1, "Failed to enable %s", av[1]);
200 return (0);
201}
202DEVCTL_COMMAND(top, enable, enable);
203
204static int
205suspend(int ac, char **av)
206{
207
208 if (ac != 2)
209 usage();
210 if (devctl_suspend(av[1]) < 0)
211 err(1, "Failed to suspend %s", av[1]);
212 return (0);
213}
214DEVCTL_COMMAND(top, suspend, suspend);
215
216static int
217resume(int ac, char **av)
218{
219
220 if (ac != 2)
221 usage();
222 if (devctl_resume(av[1]) < 0)
223 err(1, "Failed to resume %s", av[1]);
224 return (0);
225}
226DEVCTL_COMMAND(top, resume, resume);
227
228static void
229set_driver_usage(void)
230{
231
232 fprintf(stderr, "usage: devctl set driver [-f] device driver\n");
233 exit(1);
234}
235
236static int
237set_driver(int ac, char **av)
238{
239 bool force;
240 int ch;
241
242 force = false;
243 while ((ch = getopt(ac, av, "f")) != -1)
244 switch (ch) {
245 case 'f':
246 force = true;
247 break;
248 default:
249 set_driver_usage();
250 }
251 ac -= optind;
252 av += optind;
253
254 if (ac != 2)
255 set_driver_usage();
256 if (devctl_set_driver(av[0], av[1], force) < 0)
257 err(1, "Failed to set %s driver to %s", av[0], av[1]);
258 return (0);
259}
260DEVCTL_COMMAND(set, driver, set_driver);
261
29
30#include <sys/linker_set.h>
31#include <devctl.h>
32#include <err.h>
33#include <errno.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <strings.h>
38#include <unistd.h>
39
40struct devctl_command {
41 const char *name;
42 int (*handler)(int ac, char **av);
43};
44
45#define DEVCTL_DATASET(name) devctl_ ## name ## _table
46
47#define DEVCTL_COMMAND(set, name, function) \
48 static struct devctl_command function ## _devctl_command = \
49 { #name, function }; \
50 DATA_SET(DEVCTL_DATASET(set), function ## _devctl_command)
51
52#define DEVCTL_TABLE(set, name) \
53 SET_DECLARE(DEVCTL_DATASET(name), struct devctl_command); \
54 \
55 static int \
56 devctl_ ## name ## _table_handler(int ac, char **av) \
57 { \
58 return (devctl_table_handler(SET_BEGIN(DEVCTL_DATASET(name)), \
59 SET_LIMIT(DEVCTL_DATASET(name)), ac, av)); \
60 } \
61 DEVCTL_COMMAND(set, name, devctl_ ## name ## _table_handler)
62
63static int devctl_table_handler(struct devctl_command **start,
64 struct devctl_command **end, int ac, char **av);
65
66SET_DECLARE(DEVCTL_DATASET(top), struct devctl_command);
67
68DEVCTL_TABLE(top, set);
69
70static void
71usage(void)
72{
73 fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
74 "usage: devctl attach device",
75 " devctl detach [-f] device",
76 " devctl disable [-f] device",
77 " devctl enable device",
78 " devctl suspend device",
79 " devctl resume device",
80 " devctl set driver [-f] device driver");
81 exit(1);
82}
83
84static int
85devctl_table_handler(struct devctl_command **start,
86 struct devctl_command **end, int ac, char **av)
87{
88 struct devctl_command **cmd;
89
90 if (ac < 2) {
91 warnx("The %s command requires a sub-command.", av[0]);
92 return (EINVAL);
93 }
94 for (cmd = start; cmd < end; cmd++) {
95 if (strcmp((*cmd)->name, av[1]) == 0)
96 return ((*cmd)->handler(ac - 1, av + 1));
97 }
98
99 warnx("%s is not a valid sub-command of %s.", av[1], av[0]);
100 return (ENOENT);
101}
102
103static int
104help(int ac __unused, char **av __unused)
105{
106
107 usage();
108 return (0);
109}
110DEVCTL_COMMAND(top, help, help);
111
112static int
113attach(int ac, char **av)
114{
115
116 if (ac != 2)
117 usage();
118 if (devctl_attach(av[1]) < 0)
119 err(1, "Failed to attach %s", av[1]);
120 return (0);
121}
122DEVCTL_COMMAND(top, attach, attach);
123
124static void
125detach_usage(void)
126{
127
128 fprintf(stderr, "usage: devctl detach [-f] device\n");
129 exit(1);
130}
131
132static int
133detach(int ac, char **av)
134{
135 bool force;
136 int ch;
137
138 force = false;
139 while ((ch = getopt(ac, av, "f")) != -1)
140 switch (ch) {
141 case 'f':
142 force = true;
143 break;
144 default:
145 detach_usage();
146 }
147 ac -= optind;
148 av += optind;
149
150 if (ac != 1)
151 detach_usage();
152 if (devctl_detach(av[0], force) < 0)
153 err(1, "Failed to detach %s", av[0]);
154 return (0);
155}
156DEVCTL_COMMAND(top, detach, detach);
157
158static void
159disable_usage(void)
160{
161
162 fprintf(stderr, "usage: devctl disable [-f] device\n");
163 exit(1);
164}
165
166static int
167disable(int ac, char **av)
168{
169 bool force;
170 int ch;
171
172 force = false;
173 while ((ch = getopt(ac, av, "f")) != -1)
174 switch (ch) {
175 case 'f':
176 force = true;
177 break;
178 default:
179 disable_usage();
180 }
181 ac -= optind;
182 av += optind;
183
184 if (ac != 1)
185 disable_usage();
186 if (devctl_disable(av[0], force) < 0)
187 err(1, "Failed to disable %s", av[0]);
188 return (0);
189}
190DEVCTL_COMMAND(top, disable, disable);
191
192static int
193enable(int ac, char **av)
194{
195
196 if (ac != 2)
197 usage();
198 if (devctl_enable(av[1]) < 0)
199 err(1, "Failed to enable %s", av[1]);
200 return (0);
201}
202DEVCTL_COMMAND(top, enable, enable);
203
204static int
205suspend(int ac, char **av)
206{
207
208 if (ac != 2)
209 usage();
210 if (devctl_suspend(av[1]) < 0)
211 err(1, "Failed to suspend %s", av[1]);
212 return (0);
213}
214DEVCTL_COMMAND(top, suspend, suspend);
215
216static int
217resume(int ac, char **av)
218{
219
220 if (ac != 2)
221 usage();
222 if (devctl_resume(av[1]) < 0)
223 err(1, "Failed to resume %s", av[1]);
224 return (0);
225}
226DEVCTL_COMMAND(top, resume, resume);
227
228static void
229set_driver_usage(void)
230{
231
232 fprintf(stderr, "usage: devctl set driver [-f] device driver\n");
233 exit(1);
234}
235
236static int
237set_driver(int ac, char **av)
238{
239 bool force;
240 int ch;
241
242 force = false;
243 while ((ch = getopt(ac, av, "f")) != -1)
244 switch (ch) {
245 case 'f':
246 force = true;
247 break;
248 default:
249 set_driver_usage();
250 }
251 ac -= optind;
252 av += optind;
253
254 if (ac != 2)
255 set_driver_usage();
256 if (devctl_set_driver(av[0], av[1], force) < 0)
257 err(1, "Failed to set %s driver to %s", av[0], av[1]);
258 return (0);
259}
260DEVCTL_COMMAND(set, driver, set_driver);
261
262static int
263rescan(int ac, char **av)
264{
265
266 if (ac != 2)
267 usage();
268 if (devctl_rescan(av[1]) < 0)
269 err(1, "Failed to rescan %s", av[1]);
270 return (0);
271}
272DEVCTL_COMMAND(top, rescan, rescan);
273
262int
263main(int ac, char *av[])
264{
265 struct devctl_command **cmd;
266
267 if (ac == 1)
268 usage();
269 ac--;
270 av++;
271
272 SET_FOREACH(cmd, DEVCTL_DATASET(top)) {
273 if (strcmp((*cmd)->name, av[0]) == 0) {
274 if ((*cmd)->handler(ac, av) != 0)
275 return (1);
276 else
277 return (0);
278 }
279 }
280 warnx("Unknown command %s.", av[0]);
281 return (1);
282}
274int
275main(int ac, char *av[])
276{
277 struct devctl_command **cmd;
278
279 if (ac == 1)
280 usage();
281 ac--;
282 av++;
283
284 SET_FOREACH(cmd, DEVCTL_DATASET(top)) {
285 if (strcmp((*cmd)->name, av[0]) == 0) {
286 if ((*cmd)->handler(ac, av) != 0)
287 return (1);
288 else
289 return (0);
290 }
291 }
292 warnx("Unknown command %s.", av[0]);
293 return (1);
294}