xref: /freebsd/sbin/devfs/rule.c (revision 32e86a82f54826f14ea381affa6674db3aa3b5ae)
1a1dc2096SDima Dorfman /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni  *
4a1dc2096SDima Dorfman  * Copyright (c) 2002 Dima Dorfman.
5a1dc2096SDima Dorfman  * All rights reserved.
6a1dc2096SDima Dorfman  *
7a1dc2096SDima Dorfman  * Redistribution and use in source and binary forms, with or without
8a1dc2096SDima Dorfman  * modification, are permitted provided that the following conditions
9a1dc2096SDima Dorfman  * are met:
10a1dc2096SDima Dorfman  * 1. Redistributions of source code must retain the above copyright
11a1dc2096SDima Dorfman  *    notice, this list of conditions and the following disclaimer.
12a1dc2096SDima Dorfman  * 2. Redistributions in binary form must reproduce the above copyright
13a1dc2096SDima Dorfman  *    notice, this list of conditions and the following disclaimer in the
14a1dc2096SDima Dorfman  *    documentation and/or other materials provided with the distribution.
15a1dc2096SDima Dorfman  *
16a1dc2096SDima Dorfman  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17a1dc2096SDima Dorfman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18a1dc2096SDima Dorfman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19a1dc2096SDima Dorfman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20a1dc2096SDima Dorfman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21a1dc2096SDima Dorfman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22a1dc2096SDima Dorfman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23a1dc2096SDima Dorfman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24a1dc2096SDima Dorfman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25a1dc2096SDima Dorfman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26a1dc2096SDima Dorfman  * SUCH DAMAGE.
27a1dc2096SDima Dorfman  */
28a1dc2096SDima Dorfman 
29a1dc2096SDima Dorfman /*
30a1dc2096SDima Dorfman  * Rule subsystem manipulation.
31a1dc2096SDima Dorfman  */
32a1dc2096SDima Dorfman 
33a1dc2096SDima Dorfman #include <sys/param.h>
34a1dc2096SDima Dorfman #include <sys/conf.h>
35a1dc2096SDima Dorfman #include <sys/ioctl.h>
36a1dc2096SDima Dorfman 
37072af151SDima Dorfman #include <assert.h>
38a1dc2096SDima Dorfman #include <err.h>
39a1dc2096SDima Dorfman #include <errno.h>
40a1dc2096SDima Dorfman #include <grp.h>
41a1dc2096SDima Dorfman #include <pwd.h>
42a1dc2096SDima Dorfman #include <stdio.h>
43a1dc2096SDima Dorfman #include <stdlib.h>
44a1dc2096SDima Dorfman #include <string.h>
45a1dc2096SDima Dorfman #include <unistd.h>
46a1dc2096SDima Dorfman 
47a1dc2096SDima Dorfman #include "extern.h"
48a1dc2096SDima Dorfman 
494b85a12fSUlrich Spörlein static void rulespec_infp(FILE *fp, unsigned long request, devfs_rsnum rsnum);
50072af151SDima Dorfman static void rulespec_instr(struct devfs_rule *dr, const char *str,
51072af151SDima Dorfman     devfs_rsnum rsnum);
52a1dc2096SDima Dorfman static void rulespec_intok(struct devfs_rule *dr, int ac, char **av,
53a1dc2096SDima Dorfman     devfs_rsnum rsnum);
54a1dc2096SDima Dorfman static void rulespec_outfp(FILE *fp, struct devfs_rule *dr);
55a1dc2096SDima Dorfman 
56a1dc2096SDima Dorfman static command_t rule_add, rule_apply, rule_applyset;
57a1dc2096SDima Dorfman static command_t rule_del, rule_delset, rule_show, rule_showsets;
58a1dc2096SDima Dorfman 
59a1dc2096SDima Dorfman static ctbl_t ctbl_rule = {
60a1dc2096SDima Dorfman 	{ "add",		rule_add },
61a1dc2096SDima Dorfman 	{ "apply",		rule_apply },
62a1dc2096SDima Dorfman 	{ "applyset",		rule_applyset },
63a1dc2096SDima Dorfman 	{ "del",		rule_del },
64a1dc2096SDima Dorfman 	{ "delset",		rule_delset },
65a1dc2096SDima Dorfman 	{ "show",		rule_show },
66a1dc2096SDima Dorfman 	{ "showsets",		rule_showsets },
67a1dc2096SDima Dorfman 	{ NULL,			NULL }
68a1dc2096SDima Dorfman };
69a1dc2096SDima Dorfman 
70a1dc2096SDima Dorfman static struct intstr ist_type[] = {
71a1dc2096SDima Dorfman 	{ "disk",		D_DISK },
72a1dc2096SDima Dorfman 	{ "mem",		D_MEM },
73a1dc2096SDima Dorfman 	{ "tape",		D_TAPE },
74a1dc2096SDima Dorfman 	{ "tty",		D_TTY },
75a1dc2096SDima Dorfman 	{ NULL,			-1 }
76a1dc2096SDima Dorfman };
77a1dc2096SDima Dorfman 
781efe3c6bSEd Schouten static devfs_rsnum in_rsnum;
79a1dc2096SDima Dorfman 
80a1dc2096SDima Dorfman int
rule_main(int ac,char ** av)81a1dc2096SDima Dorfman rule_main(int ac, char **av)
82a1dc2096SDima Dorfman {
83a1dc2096SDima Dorfman 	struct cmd *c;
845cfe0423SPeter Grehan 	int ch;
85a1dc2096SDima Dorfman 
86a1dc2096SDima Dorfman 	setprogname("devfs rule");
87a1dc2096SDima Dorfman 	optreset = optind = 1;
88a1dc2096SDima Dorfman 	while ((ch = getopt(ac, av, "s:")) != -1)
89a1dc2096SDima Dorfman 		switch (ch) {
90a1dc2096SDima Dorfman 		case 's':
91a1dc2096SDima Dorfman 			in_rsnum = eatonum(optarg);
92a1dc2096SDima Dorfman 			break;
93a1dc2096SDima Dorfman 		default:
94a1dc2096SDima Dorfman 			usage();
95a1dc2096SDima Dorfman 		}
96a1dc2096SDima Dorfman 	ac -= optind;
97a1dc2096SDima Dorfman 	av += optind;
98a1dc2096SDima Dorfman 	if (ac < 1)
99a1dc2096SDima Dorfman 		usage();
100a1dc2096SDima Dorfman 
101a1dc2096SDima Dorfman 	for (c = ctbl_rule; c->name != NULL; ++c)
102a1dc2096SDima Dorfman 		if (strcmp(c->name, av[0]) == 0)
103a1dc2096SDima Dorfman 			exit((*c->handler)(ac, av));
104a1dc2096SDima Dorfman 	errx(1, "unknown command: %s", av[0]);
105a1dc2096SDima Dorfman }
106a1dc2096SDima Dorfman 
107a1dc2096SDima Dorfman static int
rule_add(int ac,char ** av)108a1dc2096SDima Dorfman rule_add(int ac, char **av)
109a1dc2096SDima Dorfman {
110a1dc2096SDima Dorfman 	struct devfs_rule dr;
111a1dc2096SDima Dorfman 	int rv;
112a1dc2096SDima Dorfman 
113a1dc2096SDima Dorfman 	if (ac < 2)
114a1dc2096SDima Dorfman 		usage();
115072af151SDima Dorfman 	if (strcmp(av[1], "-") == 0)
116072af151SDima Dorfman 		rulespec_infp(stdin, DEVFSIO_RADD, in_rsnum);
117072af151SDima Dorfman 	else {
118a1dc2096SDima Dorfman 		rulespec_intok(&dr, ac - 1, av + 1, in_rsnum);
119a1dc2096SDima Dorfman 		rv = ioctl(mpfd, DEVFSIO_RADD, &dr);
120a1dc2096SDima Dorfman 		if (rv == -1)
121a1dc2096SDima Dorfman 			err(1, "ioctl DEVFSIO_RADD");
122072af151SDima Dorfman 	}
123a1dc2096SDima Dorfman 	return (0);
124a1dc2096SDima Dorfman }
125a1dc2096SDima Dorfman 
126a1dc2096SDima Dorfman static int
rule_apply(int ac __unused,char ** av __unused)127a1dc2096SDima Dorfman rule_apply(int ac __unused, char **av __unused)
128a1dc2096SDima Dorfman {
129a1dc2096SDima Dorfman 	struct devfs_rule dr;
130a1dc2096SDima Dorfman 	devfs_rnum rnum;
131a1dc2096SDima Dorfman 	devfs_rid rid;
132a1dc2096SDima Dorfman 	int rv;
133a1dc2096SDima Dorfman 
134a1dc2096SDima Dorfman 	if (ac < 2)
135a1dc2096SDima Dorfman 		usage();
136a1dc2096SDima Dorfman 	if (!atonum(av[1], &rnum)) {
137072af151SDima Dorfman 		if (strcmp(av[1], "-") == 0)
138072af151SDima Dorfman 			rulespec_infp(stdin, DEVFSIO_RAPPLY, in_rsnum);
139072af151SDima Dorfman 		else {
140a1dc2096SDima Dorfman 			rulespec_intok(&dr, ac - 1, av + 1, in_rsnum);
141a1dc2096SDima Dorfman 			rv = ioctl(mpfd, DEVFSIO_RAPPLY, &dr);
142a1dc2096SDima Dorfman 			if (rv == -1)
143a1dc2096SDima Dorfman 				err(1, "ioctl DEVFSIO_RAPPLY");
144072af151SDima Dorfman 		}
145a1dc2096SDima Dorfman 	} else {
146a1dc2096SDima Dorfman 		rid = mkrid(in_rsnum, rnum);
147a1dc2096SDima Dorfman 		rv = ioctl(mpfd, DEVFSIO_RAPPLYID, &rid);
148a1dc2096SDima Dorfman 		if (rv == -1)
149a1dc2096SDima Dorfman 			err(1, "ioctl DEVFSIO_RAPPLYID");
150a1dc2096SDima Dorfman 	}
151a1dc2096SDima Dorfman 	return (0);
152a1dc2096SDima Dorfman }
153a1dc2096SDima Dorfman 
154a1dc2096SDima Dorfman static int
rule_applyset(int ac,char ** av __unused)155a1dc2096SDima Dorfman rule_applyset(int ac, char **av __unused)
156a1dc2096SDima Dorfman {
157a1dc2096SDima Dorfman 	int rv;
158a1dc2096SDima Dorfman 
159a1dc2096SDima Dorfman 	if (ac != 1)
160a1dc2096SDima Dorfman 		usage();
161a1dc2096SDima Dorfman 	rv = ioctl(mpfd, DEVFSIO_SAPPLY, &in_rsnum);
162a1dc2096SDima Dorfman 	if (rv == -1)
163a1dc2096SDima Dorfman 		err(1, "ioctl DEVFSIO_SAPPLY");
164a1dc2096SDima Dorfman 	return (0);
165a1dc2096SDima Dorfman }
166a1dc2096SDima Dorfman 
167a1dc2096SDima Dorfman static int
rule_del(int ac __unused,char ** av)168a1dc2096SDima Dorfman rule_del(int ac __unused, char **av)
169a1dc2096SDima Dorfman {
170a1dc2096SDima Dorfman 	devfs_rid rid;
171a1dc2096SDima Dorfman 	int rv;
172a1dc2096SDima Dorfman 
173a1dc2096SDima Dorfman 	if (av[1] == NULL)
174a1dc2096SDima Dorfman 		usage();
175a1dc2096SDima Dorfman 	rid = mkrid(in_rsnum, eatoi(av[1]));
176a1dc2096SDima Dorfman 	rv = ioctl(mpfd, DEVFSIO_RDEL, &rid);
177a1dc2096SDima Dorfman 	if (rv == -1)
178a1dc2096SDima Dorfman 		err(1, "ioctl DEVFSIO_RDEL");
179a1dc2096SDima Dorfman 	return (0);
180a1dc2096SDima Dorfman }
181a1dc2096SDima Dorfman 
182a1dc2096SDima Dorfman static int
rule_delset(int ac,char ** av __unused)183a1dc2096SDima Dorfman rule_delset(int ac, char **av __unused)
184a1dc2096SDima Dorfman {
185a1dc2096SDima Dorfman 	struct devfs_rule dr;
186a1dc2096SDima Dorfman 	int rv;
187a1dc2096SDima Dorfman 
188a1dc2096SDima Dorfman 	if (ac != 1)
189a1dc2096SDima Dorfman 		usage();
190a1dc2096SDima Dorfman 	memset(&dr, '\0', sizeof(dr));
191a1dc2096SDima Dorfman 	dr.dr_magic = DEVFS_MAGIC;
192a1dc2096SDima Dorfman 	dr.dr_id = mkrid(in_rsnum, 0);
193a1dc2096SDima Dorfman 	while (ioctl(mpfd, DEVFSIO_RGETNEXT, &dr) != -1) {
194a1dc2096SDima Dorfman 		rv = ioctl(mpfd, DEVFSIO_RDEL, &dr.dr_id);
195a1dc2096SDima Dorfman 		if (rv == -1)
196a1dc2096SDima Dorfman 			err(1, "ioctl DEVFSIO_RDEL");
197a1dc2096SDima Dorfman 	}
198a1dc2096SDima Dorfman 	if (errno != ENOENT)
199a1dc2096SDima Dorfman 		err(1, "ioctl DEVFSIO_RGETNEXT");
200a1dc2096SDima Dorfman 	return (0);
201a1dc2096SDima Dorfman }
202a1dc2096SDima Dorfman 
203a1dc2096SDima Dorfman static int
rule_show(int ac __unused,char ** av)204a1dc2096SDima Dorfman rule_show(int ac __unused, char **av)
205a1dc2096SDima Dorfman {
206a1dc2096SDima Dorfman 	struct devfs_rule dr;
207a1dc2096SDima Dorfman 	devfs_rnum rnum;
208a1dc2096SDima Dorfman 	int rv;
209a1dc2096SDima Dorfman 
210a1dc2096SDima Dorfman 	memset(&dr, '\0', sizeof(dr));
211a1dc2096SDima Dorfman 	dr.dr_magic = DEVFS_MAGIC;
212a1dc2096SDima Dorfman 	if (av[1] != NULL) {
213a1dc2096SDima Dorfman 		rnum = eatoi(av[1]);
214a1dc2096SDima Dorfman 		dr.dr_id = mkrid(in_rsnum, rnum - 1);
215a1dc2096SDima Dorfman 		rv = ioctl(mpfd, DEVFSIO_RGETNEXT, &dr);
216a1dc2096SDima Dorfman 		if (rv == -1)
217a1dc2096SDima Dorfman 			err(1, "ioctl DEVFSIO_RGETNEXT");
218a1dc2096SDima Dorfman 		if (rid2rn(dr.dr_id) == rnum)
219a1dc2096SDima Dorfman 			rulespec_outfp(stdout, &dr);
220a1dc2096SDima Dorfman 	} else {
221a1dc2096SDima Dorfman 		dr.dr_id = mkrid(in_rsnum, 0);
222a1dc2096SDima Dorfman 		while (ioctl(mpfd, DEVFSIO_RGETNEXT, &dr) != -1)
223a1dc2096SDima Dorfman 			rulespec_outfp(stdout, &dr);
224a1dc2096SDima Dorfman 		if (errno != ENOENT)
225a1dc2096SDima Dorfman 			err(1, "ioctl DEVFSIO_RGETNEXT");
226a1dc2096SDima Dorfman 	}
227a1dc2096SDima Dorfman 	return (0);
228a1dc2096SDima Dorfman }
229a1dc2096SDima Dorfman 
230a1dc2096SDima Dorfman static int
rule_showsets(int ac,char ** av __unused)231a1dc2096SDima Dorfman rule_showsets(int ac, char **av __unused)
232a1dc2096SDima Dorfman {
233a1dc2096SDima Dorfman 	devfs_rsnum rsnum;
234a1dc2096SDima Dorfman 
235a1dc2096SDima Dorfman 	if (ac != 1)
236a1dc2096SDima Dorfman 		usage();
237a1dc2096SDima Dorfman 	rsnum = 0;
238a1dc2096SDima Dorfman 	while (ioctl(mpfd, DEVFSIO_SGETNEXT, &rsnum) != -1)
239a1dc2096SDima Dorfman 		printf("%d\n", rsnum);
240a1dc2096SDima Dorfman 	if (errno != ENOENT)
241a1dc2096SDima Dorfman 		err(1, "ioctl DEVFSIO_SGETNEXT");
242a1dc2096SDima Dorfman 	return (0);
243a1dc2096SDima Dorfman }
244a1dc2096SDima Dorfman 
245a1dc2096SDima Dorfman int
ruleset_main(int ac,char ** av)246a1dc2096SDima Dorfman ruleset_main(int ac, char **av)
247a1dc2096SDima Dorfman {
248a1dc2096SDima Dorfman 	devfs_rsnum rsnum;
249a1dc2096SDima Dorfman 	int rv;
250a1dc2096SDima Dorfman 
251a1dc2096SDima Dorfman 	setprogname("devfs ruleset");
252a1dc2096SDima Dorfman 	if (ac < 2)
253a1dc2096SDima Dorfman 		usage();
254a1dc2096SDima Dorfman 	rsnum = eatonum(av[1]);
255a1dc2096SDima Dorfman 	rv = ioctl(mpfd, DEVFSIO_SUSE, &rsnum);
256a1dc2096SDima Dorfman 	if (rv == -1)
257a1dc2096SDima Dorfman 		err(1, "ioctl DEVFSIO_SUSE");
258a1dc2096SDima Dorfman 	return (0);
259a1dc2096SDima Dorfman }
260a1dc2096SDima Dorfman 
261a1dc2096SDima Dorfman 
262a1dc2096SDima Dorfman /*
263072af151SDima Dorfman  * Input rules from a file (probably the standard input).  This
264072af151SDima Dorfman  * differs from the other rulespec_in*() routines in that it also
265072af151SDima Dorfman  * calls ioctl() for the rules, since it is impractical (and not very
266072af151SDima Dorfman  * useful) to return a list (or array) of rules, just so the caller
26799144520SEitan Adler  * can call ioctl() for each of them.
268072af151SDima Dorfman  */
269072af151SDima Dorfman static void
rulespec_infp(FILE * fp,unsigned long request,devfs_rsnum rsnum)2705159643aSDima Dorfman rulespec_infp(FILE *fp, unsigned long request, devfs_rsnum rsnum)
271072af151SDima Dorfman {
272072af151SDima Dorfman 	struct devfs_rule dr;
273072af151SDima Dorfman 	char *line;
274072af151SDima Dorfman 	int rv;
275072af151SDima Dorfman 
276072af151SDima Dorfman 	assert(fp == stdin);	/* XXX: De-hardcode "stdin" from error msg. */
277072af151SDima Dorfman 	while (efgetln(fp, &line)) {
278072af151SDima Dorfman 		rulespec_instr(&dr, line, rsnum);
2795159643aSDima Dorfman 		rv = ioctl(mpfd, request, &dr);
280072af151SDima Dorfman 		if (rv == -1)
281072af151SDima Dorfman 			err(1, "ioctl");
282072af151SDima Dorfman 		free(line);	/* efgetln() always malloc()s. */
283072af151SDima Dorfman 	}
284072af151SDima Dorfman 	if (ferror(stdin))
285072af151SDima Dorfman 		err(1, "stdin");
286072af151SDima Dorfman }
287072af151SDima Dorfman 
288072af151SDima Dorfman /*
289072af151SDima Dorfman  * Construct a /struct devfs_rule/ from a string.
290072af151SDima Dorfman  */
291072af151SDima Dorfman static void
rulespec_instr(struct devfs_rule * dr,const char * str,devfs_rsnum rsnum)292072af151SDima Dorfman rulespec_instr(struct devfs_rule *dr, const char *str, devfs_rsnum rsnum)
293072af151SDima Dorfman {
294072af151SDima Dorfman 	char **av;
295072af151SDima Dorfman 	int ac;
296072af151SDima Dorfman 
297072af151SDima Dorfman 	tokenize(str, &ac, &av);
298072af151SDima Dorfman 	if (ac == 0)
299072af151SDima Dorfman 		errx(1, "unexpected end of rulespec");
300072af151SDima Dorfman 	rulespec_intok(dr, ac, av, rsnum);
301072af151SDima Dorfman 	free(av[0]);
302072af151SDima Dorfman 	free(av);
303072af151SDima Dorfman }
304072af151SDima Dorfman 
305072af151SDima Dorfman /*
306a1dc2096SDima Dorfman  * Construct a /struct devfs_rule/ from ac and av.
307a1dc2096SDima Dorfman  */
308a1dc2096SDima Dorfman static void
rulespec_intok(struct devfs_rule * dr,int ac __unused,char ** av,devfs_rsnum rsnum)309a1dc2096SDima Dorfman rulespec_intok(struct devfs_rule *dr, int ac __unused, char **av,
310a1dc2096SDima Dorfman     devfs_rsnum rsnum)
311a1dc2096SDima Dorfman {
312a1dc2096SDima Dorfman 	struct intstr *is;
313a1dc2096SDima Dorfman 	struct passwd *pw;
314a1dc2096SDima Dorfman 	struct group *gr;
315a1dc2096SDima Dorfman 	devfs_rnum rnum;
3161cf7cec3SDima Dorfman 	void *set;
317a1dc2096SDima Dorfman 
318a1dc2096SDima Dorfman 	memset(dr, '\0', sizeof(*dr));
319a1dc2096SDima Dorfman 
320a1dc2096SDima Dorfman 	/*
321a1dc2096SDima Dorfman 	 * We don't maintain ac hereinafter.
322a1dc2096SDima Dorfman 	 */
323a1dc2096SDima Dorfman 	if (av[0] == NULL)
324a1dc2096SDima Dorfman 		errx(1, "unexpected end of rulespec");
325a1dc2096SDima Dorfman 
326a1dc2096SDima Dorfman 	/* If the first argument is an integer, treat it as a rule number. */
327a1dc2096SDima Dorfman 	if (!atonum(av[0], &rnum))
328a1dc2096SDima Dorfman 		rnum = 0;		/* auto-number */
329a1dc2096SDima Dorfman 	else
330a1dc2096SDima Dorfman 		++av;
331a1dc2096SDima Dorfman 
332a1dc2096SDima Dorfman 	/*
333a1dc2096SDima Dorfman 	 * These aren't table-driven since that would result in more
334a1dc2096SDima Dorfman 	 * tiny functions than I care to deal with.
335a1dc2096SDima Dorfman 	 */
336a1dc2096SDima Dorfman 	for (;;) {
337a1dc2096SDima Dorfman 		if (av[0] == NULL)
338a1dc2096SDima Dorfman 			break;
339a1dc2096SDima Dorfman 		else if (strcmp(av[0], "type") == 0) {
340a1dc2096SDima Dorfman 			if (av[1] == NULL)
341a1dc2096SDima Dorfman 				errx(1, "expecting argument for type");
342a1dc2096SDima Dorfman 			for (is = ist_type; is->s != NULL; ++is)
343a1dc2096SDima Dorfman 				if (strcmp(av[1], is->s) == 0) {
344a1dc2096SDima Dorfman 					dr->dr_dswflags |= is->i;
345a1dc2096SDima Dorfman 					break;
346a1dc2096SDima Dorfman 				}
347a1dc2096SDima Dorfman 			if (is->s == NULL)
348a1dc2096SDima Dorfman 				errx(1, "unknown type: %s", av[1]);
349a1dc2096SDima Dorfman 			dr->dr_icond |= DRC_DSWFLAGS;
350a1dc2096SDima Dorfman 			av += 2;
351a1dc2096SDima Dorfman 		} else if (strcmp(av[0], "path") == 0) {
352a1dc2096SDima Dorfman 			if (av[1] == NULL)
353a1dc2096SDima Dorfman 				errx(1, "expecting argument for path");
354a1dc2096SDima Dorfman 			if (strlcpy(dr->dr_pathptrn, av[1], DEVFS_MAXPTRNLEN)
355a1dc2096SDima Dorfman 			    >= DEVFS_MAXPTRNLEN)
356a1dc2096SDima Dorfman 				warnx("pattern specified too long; truncated");
357a1dc2096SDima Dorfman 			dr->dr_icond |= DRC_PATHPTRN;
358a1dc2096SDima Dorfman 			av += 2;
359a1dc2096SDima Dorfman 		} else
360a1dc2096SDima Dorfman 			break;
361a1dc2096SDima Dorfman 	}
3621cf7cec3SDima Dorfman 	while (av[0] != NULL) {
3631cf7cec3SDima Dorfman 		if (strcmp(av[0], "hide") == 0) {
364a1dc2096SDima Dorfman 			dr->dr_iacts |= DRA_BACTS;
365a1dc2096SDima Dorfman 			dr->dr_bacts |= DRB_HIDE;
366a1dc2096SDima Dorfman 			++av;
367a1dc2096SDima Dorfman 		} else if (strcmp(av[0], "unhide") == 0) {
368a1dc2096SDima Dorfman 			dr->dr_iacts |= DRA_BACTS;
369a1dc2096SDima Dorfman 			dr->dr_bacts |= DRB_UNHIDE;
370a1dc2096SDima Dorfman 			++av;
371a1dc2096SDima Dorfman 		} else if (strcmp(av[0], "user") == 0) {
372a1dc2096SDima Dorfman 			if (av[1] == NULL)
373a1dc2096SDima Dorfman 				errx(1, "expecting argument for user");
374a1dc2096SDima Dorfman 			dr->dr_iacts |= DRA_UID;
375a1dc2096SDima Dorfman 			pw = getpwnam(av[1]);
376a1dc2096SDima Dorfman 			if (pw != NULL)
377a1dc2096SDima Dorfman 				dr->dr_uid = pw->pw_uid;
378a1dc2096SDima Dorfman 			else
379a1dc2096SDima Dorfman 				dr->dr_uid = eatoi(av[1]); /* XXX overflow */
380a1dc2096SDima Dorfman 			av += 2;
381a1dc2096SDima Dorfman 		} else if (strcmp(av[0], "group") == 0) {
382a1dc2096SDima Dorfman 			if (av[1] == NULL)
383a1dc2096SDima Dorfman 				errx(1, "expecting argument for group");
384a1dc2096SDima Dorfman 			dr->dr_iacts |= DRA_GID;
385a1dc2096SDima Dorfman 			gr = getgrnam(av[1]);
386a1dc2096SDima Dorfman 			if (gr != NULL)
387a1dc2096SDima Dorfman 				dr->dr_gid = gr->gr_gid;
388a1dc2096SDima Dorfman 			else
389a1dc2096SDima Dorfman 				dr->dr_gid = eatoi(av[1]); /* XXX overflow */
390a1dc2096SDima Dorfman 			av += 2;
391a1dc2096SDima Dorfman 		} else if (strcmp(av[0], "mode") == 0) {
392a1dc2096SDima Dorfman 			if (av[1] == NULL)
393a1dc2096SDima Dorfman 				errx(1, "expecting argument for mode");
394a1dc2096SDima Dorfman 			dr->dr_iacts |= DRA_MODE;
3951cf7cec3SDima Dorfman 			set = setmode(av[1]);
3961cf7cec3SDima Dorfman 			if (set == NULL)
3974c2f7823SMaxim Konovalov 				errx(1, "invalid mode: %s", av[1]);
3981cf7cec3SDima Dorfman 			dr->dr_mode = getmode(set, 0);
399a1dc2096SDima Dorfman 			av += 2;
400a1dc2096SDima Dorfman 		} else if (strcmp(av[0], "include") == 0) {
401a1dc2096SDima Dorfman 			if (av[1] == NULL)
402a1dc2096SDima Dorfman 				errx(1, "expecting argument for include");
403a1dc2096SDima Dorfman 			dr->dr_iacts |= DRA_INCSET;
404a1dc2096SDima Dorfman 			dr->dr_incset = eatonum(av[1]);
405a1dc2096SDima Dorfman 			av += 2;
406a1dc2096SDima Dorfman 		} else
407a1dc2096SDima Dorfman 			errx(1, "unknown argument: %s", av[0]);
408a1dc2096SDima Dorfman 	}
409a1dc2096SDima Dorfman 
410a1dc2096SDima Dorfman 	dr->dr_id = mkrid(rsnum, rnum);
411a1dc2096SDima Dorfman 	dr->dr_magic = DEVFS_MAGIC;
412a1dc2096SDima Dorfman }
413a1dc2096SDima Dorfman 
414a1dc2096SDima Dorfman /*
415a1dc2096SDima Dorfman  * Write a human-readable (and machine-parsable, by rulespec_in*())
416a1dc2096SDima Dorfman  * representation of dr to bufp.  *bufp should be free(3)'d when the
417a1dc2096SDima Dorfman  * caller is finished with it.
418a1dc2096SDima Dorfman  */
419a1dc2096SDima Dorfman static void
rulespec_outfp(FILE * fp,struct devfs_rule * dr)420a1dc2096SDima Dorfman rulespec_outfp(FILE *fp, struct devfs_rule *dr)
421a1dc2096SDima Dorfman {
422a1dc2096SDima Dorfman 	struct intstr *is;
423a1dc2096SDima Dorfman 	struct passwd *pw;
424a1dc2096SDima Dorfman 	struct group *gr;
425a1dc2096SDima Dorfman 
426a1dc2096SDima Dorfman 	fprintf(fp, "%d", rid2rn(dr->dr_id));
427a1dc2096SDima Dorfman 
428a1dc2096SDima Dorfman 	if (dr->dr_icond & DRC_DSWFLAGS)
429a1dc2096SDima Dorfman 		for (is = ist_type; is->s != NULL; ++is)
430a1dc2096SDima Dorfman 			if (dr->dr_dswflags & is->i)
431a1dc2096SDima Dorfman 				fprintf(fp, " type %s", is->s);
432a1dc2096SDima Dorfman 	if (dr->dr_icond & DRC_PATHPTRN)
433a1dc2096SDima Dorfman 		fprintf(fp, " path %s", dr->dr_pathptrn);
434a1dc2096SDima Dorfman 
435a1dc2096SDima Dorfman 	if (dr->dr_iacts & DRA_BACTS) {
436a1dc2096SDima Dorfman 		if (dr->dr_bacts & DRB_HIDE)
437a1dc2096SDima Dorfman 			fprintf(fp, " hide");
438a1dc2096SDima Dorfman 		if (dr->dr_bacts & DRB_UNHIDE)
439a1dc2096SDima Dorfman 			fprintf(fp, " unhide");
440a1dc2096SDima Dorfman 	}
441a1dc2096SDima Dorfman 	if (dr->dr_iacts & DRA_UID) {
442a1dc2096SDima Dorfman 		pw = getpwuid(dr->dr_uid);
443a1dc2096SDima Dorfman 		if (pw == NULL)
444a1dc2096SDima Dorfman 			fprintf(fp, " user %d", dr->dr_uid);
445a1dc2096SDima Dorfman 		else
446a1dc2096SDima Dorfman 			fprintf(fp, " user %s", pw->pw_name);
447a1dc2096SDima Dorfman 	}
448a1dc2096SDima Dorfman 	if (dr->dr_iacts & DRA_GID) {
449a1dc2096SDima Dorfman 		gr = getgrgid(dr->dr_gid);
450a1dc2096SDima Dorfman 		if (gr == NULL)
451a1dc2096SDima Dorfman 			fprintf(fp, " group %d", dr->dr_gid);
452a1dc2096SDima Dorfman 		else
453a1dc2096SDima Dorfman 			fprintf(fp, " group %s", gr->gr_name);
454a1dc2096SDima Dorfman 	}
455a1dc2096SDima Dorfman 	if (dr->dr_iacts & DRA_MODE)
456a1dc2096SDima Dorfman 		fprintf(fp, " mode %o", dr->dr_mode);
457a1dc2096SDima Dorfman 	if (dr->dr_iacts & DRA_INCSET)
458a1dc2096SDima Dorfman 		fprintf(fp, " include %d", dr->dr_incset);
459a1dc2096SDima Dorfman 
460a1dc2096SDima Dorfman 	fprintf(fp, "\n");
461a1dc2096SDima Dorfman }
462