2 * Copyright (c) 2009 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Alex Hornung <ahornung@gmail.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 #include <sys/ioctl.h>
35 #include <sys/types.h>
44 #include <vfs/devfs/devfs_rules.h>
45 #include <sys/device.h>
47 void dump_config(void);
48 void rule_init(struct devfs_rule
*rule
, char *name
);
49 int rule_check_num_args(char **tokens
, int num
);
50 void rule_group(char **tokens
);
51 void rule_parse_groups(void);
52 void rule_clear_groups(void);
53 void rule_clear_rules(void);
54 void rule_perm(char **tokens
);
55 void rule_link(char **tokens
);
56 void rule_hide(char **tokens
);
57 void rule_show(char **tokens
);
58 struct devfs_rule
*get_group(char *name
);
59 struct devfs_rule
*get_rule(char *name
);
60 void put_rule(struct devfs_rule
*rule
);
63 int rule_ioctl(unsigned long cmd
, struct devfs_rule
*rule
);
64 int read_config(char *name
);
65 int process_line(FILE* fd
);
70 static struct devfs_rule dummy_rule
;
71 static int verbose
= 0;
74 TAILQ_HEAD(devfs_rule_head
, devfs_rule
);
76 static struct devfs_rule_head devfs_rule_list
= TAILQ_HEAD_INITIALIZER(devfs_rule_list
);
77 static struct devfs_rule_head devfs_group_list
= TAILQ_HEAD_INITIALIZER(devfs_group_list
);
83 struct devfs_rule
*rule
;
87 TAILQ_FOREACH(rule
, &devfs_rule_list
, link
) {
88 printf("-----------------------------------------\n");
91 printf("device type ");
92 switch (rule
->dev_type
) {
109 printf("%s\n", rule
->name
);
112 printf("only jails?\t%s\n", (rule
->rule_type
& DEVFS_RULE_JAIL
)?"yes":"no");
114 printf("Action:\t\t");
115 if (rule
->rule_type
& DEVFS_RULE_LINK
) {
116 printf("link to %s\n", rule
->linkname
);
117 } else if (rule
->rule_type
& DEVFS_RULE_HIDE
) {
119 } else if (rule
->rule_type
& DEVFS_RULE_SHOW
) {
122 pwd
= getpwuid(rule
->uid
);
123 grp
= getgrgid(rule
->gid
);
124 printf("set mode: %o\n\t\tset owner: %s\n\t\tset group: %s\n",
125 rule
->mode
, pwd
->pw_name
, grp
->gr_name
);
128 printf("-----------------------------------------\n");
132 rule_init(struct devfs_rule
*rule
, char *name
)
136 if (!strcmp(name
, "D_TAPE")) {
137 rule
->rule_type
= DEVFS_RULE_TYPE
;
138 rule
->dev_type
= D_TAPE
;
139 } else if (!strcmp(name
, "D_DISK")) {
140 rule
->rule_type
= DEVFS_RULE_TYPE
;
141 rule
->dev_type
= D_DISK
;
142 } else if (!strcmp(name
, "D_TTY")) {
143 rule
->rule_type
= DEVFS_RULE_TYPE
;
144 rule
->dev_type
= D_TTY
;
145 } else if (!strcmp(name
, "D_MEM")) {
146 rule
->rule_type
= DEVFS_RULE_TYPE
;
147 rule
->dev_type
= D_MEM
;
151 rule
->name
= malloc(len
+1);
152 strlcpy(rule
->name
, name
, len
+1);
153 rule
->rule_type
= DEVFS_RULE_NAME
;
157 rule
->rule_type
|= DEVFS_RULE_JAIL
;
161 rule_check_num_args(char **tokens
, int num
)
164 for (i
= 0; tokens
[i
] != NULL
; i
++);
167 printf("This line in the configuration file is incorrect."
168 " It has %d words, but %d were expected\n",
171 for (i
= 0; *(tokens
[i
]); i
++) {
183 rule_group(char **tokens
)
186 struct devfs_rule
*group
, *rule
;
188 rule
= get_rule(NULL
);
189 rule_init(rule
, tokens
[0]);
191 if (!(group
= get_group(tokens
[2]))) {
192 group
= get_rule(NULL
);
193 len
= strlen(tokens
[2]);
195 group
->name
= malloc(len
+1);
196 strlcpy(group
->name
, tokens
[2], len
+1);
197 TAILQ_INSERT_TAIL(&devfs_group_list
, group
, link
);
201 TAILQ_INSERT_TAIL(&devfs_rule_list
, rule
, link
);
205 rule_parse_groups(void)
207 struct devfs_rule
*rule
, *group
;
209 TAILQ_FOREACH(rule
, &devfs_rule_list
, link
) {
210 if ((group
= rule
->group
)) {
212 rule
->rule_type
|= group
->rule_type
;
213 rule
->mode
= group
->mode
;
214 rule
->uid
= group
->uid
;
215 rule
->gid
= group
->gid
;
217 if (group
->linkname
) {
218 rule
->linknamlen
= group
->linknamlen
;
219 rule
->linkname
= malloc(group
->linknamlen
+1);
220 strlcpy(rule
->linkname
, group
->linkname
, group
->linknamlen
+1);
227 rule_clear_groups(void)
229 struct devfs_rule
*rule
, *rule1
;
230 TAILQ_FOREACH_MUTABLE(rule
, &devfs_group_list
, link
, rule1
) {
231 TAILQ_REMOVE(&devfs_group_list
, rule
, link
);
237 rule_clear_rules(void)
239 struct devfs_rule
*rule
, *rule1
;
240 TAILQ_FOREACH_MUTABLE(rule
, &devfs_rule_list
, link
, rule1
) {
241 TAILQ_REMOVE(&devfs_rule_list
, rule
, link
);
247 rule_perm(char **tokens
)
249 struct devfs_rule
*rule
;
252 rule
= get_rule(tokens
[0]);
253 rule_init(rule
, tokens
[0]);
254 rule
->mode
= strtol(tokens
[2], NULL
, 8);
255 if ((pwd
= getpwnam(tokens
[3])))
256 rule
->uid
= pwd
->pw_uid
;
257 if ((grp
= getgrnam(tokens
[4])))
258 rule
->gid
= grp
->gr_gid
;
259 TAILQ_INSERT_TAIL(&devfs_rule_list
, rule
, link
);
263 rule_link(char **tokens
)
265 struct devfs_rule
*rule
;
268 rule
= get_rule(tokens
[0]);
269 rule_init(rule
, tokens
[0]);
271 len
= strlen(tokens
[2]);
272 rule
->linknamlen
= len
;
273 rule
->linkname
= malloc(len
+1);
274 strlcpy(rule
->linkname
, tokens
[2], len
+1);
275 rule
->rule_type
|= DEVFS_RULE_LINK
;
277 TAILQ_INSERT_TAIL(&devfs_rule_list
, rule
, link
);
281 rule_hide(char **tokens
)
283 struct devfs_rule
*rule
;
285 rule
= get_rule(tokens
[0]);
286 rule_init(rule
, tokens
[0]);
288 rule
->rule_type
|= DEVFS_RULE_HIDE
;
290 TAILQ_INSERT_TAIL(&devfs_rule_list
, rule
, link
);
294 rule_show(char **tokens
)
296 struct devfs_rule
*rule
;
298 rule
= get_rule(tokens
[0]);
299 rule_init(rule
, tokens
[0]);
301 rule
->rule_type
|= DEVFS_RULE_SHOW
;
303 TAILQ_INSERT_TAIL(&devfs_rule_list
, rule
, link
);
307 get_group(char *name
)
309 struct devfs_rule
*rule
, *found
= NULL
;
311 TAILQ_FOREACH(rule
, &devfs_group_list
, link
) {
312 if (!strcmp(rule
->name
, name
)) {
324 struct devfs_rule
*rule
;
326 if ((name
== NULL
) || (!(rule
= get_group(name
)))) {
327 rule
= (struct devfs_rule
*)malloc(sizeof(struct devfs_rule
));
328 memset(rule
, 0, sizeof(struct devfs_rule
));
335 put_rule(struct devfs_rule
*rule
)
341 free(rule
->linkname
);
344 free(rule
->mntpoint
);
352 if ((dev_fd
= open("/dev/devfs", O_RDWR
)) == -1) {
353 perror("open /dev/devfs error\n");
368 rule_ioctl(unsigned long cmd
, struct devfs_rule
*rule
)
370 if (ioctl(dev_fd
, cmd
, rule
) == -1) {
371 perror("ioctl error");
379 read_config(char *name
)
382 if ((fd
= fopen(name
, "r")) == NULL
) {
383 printf("Error opening config file %s\n", name
);
388 while (process_line(fd
) == 0);
397 process_line(FILE* fd
)
405 while (((c
= fgetc(fd
)) != EOF
) && (c
!= '\n')) {
406 buffer
[i
++] = (char)c
;
407 if (i
== (sizeof(buffer
) -1))
411 if (feof(fd
) || ferror(fd
))
414 while (((buffer
[c
] == ' ') || (buffer
[c
] == '\t')) && (c
< i
)) c
++;
415 tokens
[0] = &buffer
[c
];
416 for (n
= 1, c
= 0; c
< i
; c
++) {
417 if ((buffer
[c
] == ' ') || (buffer
[c
] == '\t')) {
419 while (((buffer
[c
] == ' ') || (buffer
[c
] == '\t')) && (c
< i
)) c
++;
420 tokens
[n
++] = &buffer
[c
];
429 printf("Currently processing verb/command: %s\n", (tokens
[0][0] == '#')?(tokens
[0]):(tokens
[1]));
431 if (!strcmp(tokens
[0], "#include")) {
432 /* This is an include instruction */
433 if (!rule_check_num_args(tokens
, 2))
434 read_config(tokens
[1]);
435 } else if (!strcmp(tokens
[0], "#jail")) {
436 /* This is a jail instruction */
437 if (!rule_check_num_args(tokens
, 2))
438 jail
= (tokens
[1][0] == 'y')?1:0;
439 } else if (!strcmp(tokens
[1], "group")) {
440 /* This is a group rule */
441 if (!rule_check_num_args(tokens
, 3))
443 } else if (!strcmp(tokens
[1], "perm")) {
444 /* This is a perm rule */
445 if (!rule_check_num_args(tokens
, 5))
447 } else if (!strcmp(tokens
[1], "link")) {
448 /* This is a link rule */
449 if (!rule_check_num_args(tokens
, 3))
451 } else if (!strcmp(tokens
[1], "hide")) {
452 /* This is a hide rule */
453 if (!rule_check_num_args(tokens
, 2))
455 } else if (!strcmp(tokens
[1], "show")) {
456 /* This is a show rule */
457 if (!rule_check_num_args(tokens
, 2))
460 printf("Unknown verb %s\n", tokens
[1]);
469 printf("Usage: devfsctl <commands> [options]\n");
470 printf("Valid commands are:\n");
471 printf(" -a\n\t Loads all read rules into the kernel and "
473 printf(" -c\n\t Clears all rules stored in the kernel but "
474 "does not reset the nodes\n");
475 printf(" -d\n\t Dumps the rules that have been loaded to the "
476 "screen to verify syntax\n");
477 printf(" -r\n\t Resets all devfs_nodes but does not clear "
478 "the rules stored\n");
480 printf("\nValid options and its arguments are:\n");
481 printf(" -f <config_file>\n\t Specifies the configuration file "
483 printf(" -m <mount_point>\n\t Specifies a mount point to which "
484 "the command will apply. Defaults to *\n");
485 printf(" -v\n\t Enables verbose mode\n");
491 int main(int argc
, char *argv
[])
493 struct devfs_rule
*rule
;
496 char farg
[1024], marg
[1024];
497 int fflag
= 0, dflag
= 0, mflag
= 0;
498 int aflag
= 0, cflag
= 0, rflag
= 0;
500 while ((ch
= getopt(argc
, argv
, "acdf:hrvm:")) != -1) {
506 strlcpy(farg
, optarg
, 1024);
510 strlcpy(marg
, optarg
, 1024);
541 dummy_rule
.mntpoint
= malloc(len
+1);
542 strlcpy(dummy_rule
.mntpoint
, marg
, len
+1);
543 dummy_rule
.mntpointlen
= len
;
546 rule_ioctl(DEVFS_RULE_CLEAR
, &dummy_rule
);
553 dummy_rule
.mntpoint
= malloc(len
+1);
554 strlcpy(dummy_rule
.mntpoint
, marg
, len
+1);
555 dummy_rule
.mntpointlen
= len
;
557 rule_ioctl(DEVFS_RULE_RESET
, &dummy_rule
);
580 TAILQ_FOREACH(rule
, &devfs_rule_list
, link
) {
581 rule
->mntpoint
= malloc(len
+1);
582 strlcpy(rule
->mntpoint
, marg
, len
+1);
583 rule
->mntpointlen
= len
;
584 rule_ioctl(DEVFS_RULE_ADD
, rule
);
587 dummy_rule
.mntpoint
= malloc(len
+1);
588 strlcpy(dummy_rule
.mntpoint
, marg
, len
+1);
589 dummy_rule
.mntpointlen
= len
;
590 rule_ioctl(DEVFS_RULE_APPLY
, &dummy_rule
);