Implement this (quoted from the updated man page): If the first token
of a rule specification is a single dash (``-''), rules are read from the standard input and the rest of the specification is ignored.
This commit is contained in:
parent
e3d769e493
commit
833e15959c
@ -143,6 +143,10 @@ and the actions determine what should be done when a rule matches a node.
|
||||
For example, a rule can be written that sets the GID to
|
||||
.Li games
|
||||
for all devices with major number 53.
|
||||
If the first token of a rule specification is a single dash
|
||||
.Pq Dq - ,
|
||||
rules are read from the standard input and the rest of the specification
|
||||
is ignored.
|
||||
.Pp
|
||||
The following conditions are recognized.
|
||||
Conditions are ANDed together when matching a device;
|
||||
@ -311,6 +315,28 @@ will be applied to all nodes.
|
||||
Since hiding all nodes isn't very useful, we can undo like so:
|
||||
.Pp
|
||||
.Dl devfs rule apply unhide
|
||||
.Pp
|
||||
which applies
|
||||
.Cm unhide
|
||||
to all the nodes,
|
||||
causing them to reappear.
|
||||
.Pp
|
||||
.Dl cat my_rules | devfs rule -s 10 add -
|
||||
.Pp
|
||||
Add all the rules from the file
|
||||
.Pa my_rules
|
||||
to ruleset 10.
|
||||
.Pp
|
||||
.Dl devfs rule -s 20 show | devfs rule -s 10 add -
|
||||
.Pp
|
||||
Since
|
||||
.Cm show
|
||||
outputs valid rules,
|
||||
this feature can be used to copy rulesets.
|
||||
The above copies all the rules from ruleset 20 into ruleset 10.
|
||||
The rule numbers are preserved,
|
||||
but ruleset 10 may already have rules with non-conflicting numbers
|
||||
(these will be preserved).
|
||||
.Sh SEE ALSO
|
||||
.Xr jail 2 ,
|
||||
.Xr glob 3 ,
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*-
|
||||
* Copyright (c) 2002 Dima Dorfman.
|
||||
* Copyright (c) 2001, 2002 Dima Dorfman.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -32,7 +32,9 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/queue.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <fcntl.h>
|
||||
#include <paths.h>
|
||||
@ -131,6 +133,93 @@ eatonum(const char *s)
|
||||
return (num);
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a line from a /FILE/. If the return value isn't 0, it is the
|
||||
* length of the line, a pointer to which exists in /line/. It is the
|
||||
* caller's responsibility to free(3) it. If the return value is 0,
|
||||
* there was an error or we reached EOF, and /line/ is undefined (so,
|
||||
* obviously, the caller shouldn't try to free(3) it).
|
||||
*/
|
||||
size_t
|
||||
efgetln(FILE *fp, char **line)
|
||||
{
|
||||
size_t rv;
|
||||
char *cp;
|
||||
|
||||
cp = fgetln(fp, &rv);
|
||||
if (cp == NULL) {
|
||||
*line = NULL;
|
||||
return (rv);
|
||||
}
|
||||
if (cp[rv - 1] == '\n') {
|
||||
cp[rv - 1] = '\0';
|
||||
*line = strdup(cp);
|
||||
if (*line == NULL)
|
||||
errx(1, "cannot allocate memory");
|
||||
--rv;
|
||||
} else {
|
||||
*line = malloc(rv + 1);
|
||||
if (*line == NULL)
|
||||
errx(1, "cannot allocate memory");
|
||||
memcpy(*line, cp, rv);
|
||||
*line[rv] = '\0';
|
||||
}
|
||||
assert(rv == strlen(*line));
|
||||
return (rv);
|
||||
}
|
||||
|
||||
struct ptrstq {
|
||||
STAILQ_ENTRY(ptrstq) tq;
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
/*
|
||||
* Create an argument vector from /line/. The caller must free(3)
|
||||
* /avp/, and /avp[0]/ when the argument vector is no longer
|
||||
* needed unless /acp/ is 0, in which case /avp/ is undefined.
|
||||
* /avp/ is NULL-terminated, so it is actually one longer than /acp/.
|
||||
*/
|
||||
void
|
||||
tokenize(const char *line, int *acp, char ***avp)
|
||||
{
|
||||
static const char *delims = " \t\n";
|
||||
struct ptrstq *pt;
|
||||
STAILQ_HEAD(, ptrstq) plist;
|
||||
char **ap, *cp, *wline, *xcp;
|
||||
|
||||
line += strspn(line, delims);
|
||||
wline = strdup(line);
|
||||
if (wline == NULL)
|
||||
errx(1, "cannot allocate memory");
|
||||
|
||||
STAILQ_INIT(&plist);
|
||||
for (xcp = wline, *acp = 0;
|
||||
(cp = strsep(&xcp, delims)) != NULL;)
|
||||
if (*cp != '\0') {
|
||||
pt = calloc(1, sizeof(*pt));
|
||||
if (pt == NULL)
|
||||
errx(1, "cannot allocate memory");
|
||||
pt->ptr = cp;
|
||||
STAILQ_INSERT_TAIL(&plist, pt, tq);
|
||||
++*acp;
|
||||
}
|
||||
if (*acp == 0)
|
||||
return;
|
||||
assert(STAILQ_FIRST(&plist)->ptr == wline);
|
||||
*avp = malloc(sizeof(**avp) * (*acp + 1));
|
||||
if (*avp == NULL)
|
||||
errx(1, "cannot allocate memory");
|
||||
for (ap = *avp; !STAILQ_EMPTY(&plist);) {
|
||||
pt = STAILQ_FIRST(&plist);
|
||||
*ap = pt->ptr;
|
||||
++ap;
|
||||
assert(ap <= *avp + (*acp));
|
||||
STAILQ_REMOVE_HEAD(&plist, tq);
|
||||
free(pt);
|
||||
}
|
||||
*ap = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
usage(void)
|
||||
{
|
||||
|
@ -48,6 +48,8 @@ command_t rule_main, ruleset_main;
|
||||
int atonum(const char *, uint16_t *);
|
||||
int eatoi(const char *);
|
||||
uint16_t eatonum(const char *);
|
||||
size_t efgetln(FILE *, char **);
|
||||
void tokenize(const char *, int *, char ***);
|
||||
void usage(void) __dead2;
|
||||
|
||||
extern int mpfd; /* Mount-point file descriptor. */
|
||||
|
@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/conf.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <grp.h>
|
||||
@ -46,6 +47,9 @@ __FBSDID("$FreeBSD$");
|
||||
|
||||
#include "extern.h"
|
||||
|
||||
static void rulespec_infp(FILE *fp, int cmd, devfs_rsnum rsnum);
|
||||
static void rulespec_instr(struct devfs_rule *dr, const char *str,
|
||||
devfs_rsnum rsnum);
|
||||
static void rulespec_intok(struct devfs_rule *dr, int ac, char **av,
|
||||
devfs_rsnum rsnum);
|
||||
static void rulespec_outfp(FILE *fp, struct devfs_rule *dr);
|
||||
@ -109,10 +113,14 @@ rule_add(int ac, char **av)
|
||||
|
||||
if (ac < 2)
|
||||
usage();
|
||||
rulespec_intok(&dr, ac - 1, av + 1, in_rsnum);
|
||||
rv = ioctl(mpfd, DEVFSIO_RADD, &dr);
|
||||
if (rv == -1)
|
||||
err(1, "ioctl DEVFSIO_RADD");
|
||||
if (strcmp(av[1], "-") == 0)
|
||||
rulespec_infp(stdin, DEVFSIO_RADD, in_rsnum);
|
||||
else {
|
||||
rulespec_intok(&dr, ac - 1, av + 1, in_rsnum);
|
||||
rv = ioctl(mpfd, DEVFSIO_RADD, &dr);
|
||||
if (rv == -1)
|
||||
err(1, "ioctl DEVFSIO_RADD");
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -127,10 +135,14 @@ rule_apply(int ac __unused, char **av __unused)
|
||||
if (ac < 2)
|
||||
usage();
|
||||
if (!atonum(av[1], &rnum)) {
|
||||
rulespec_intok(&dr, ac - 1, av + 1, in_rsnum);
|
||||
rv = ioctl(mpfd, DEVFSIO_RAPPLY, &dr);
|
||||
if (rv == -1)
|
||||
err(1, "ioctl DEVFSIO_RAPPLY");
|
||||
if (strcmp(av[1], "-") == 0)
|
||||
rulespec_infp(stdin, DEVFSIO_RAPPLY, in_rsnum);
|
||||
else {
|
||||
rulespec_intok(&dr, ac - 1, av + 1, in_rsnum);
|
||||
rv = ioctl(mpfd, DEVFSIO_RAPPLY, &dr);
|
||||
if (rv == -1)
|
||||
err(1, "ioctl DEVFSIO_RAPPLY");
|
||||
}
|
||||
} else {
|
||||
rid = mkrid(in_rsnum, rnum);
|
||||
rv = ioctl(mpfd, DEVFSIO_RAPPLYID, &rid);
|
||||
@ -248,6 +260,49 @@ ruleset_main(int ac, char **av)
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Input rules from a file (probably the standard input). This
|
||||
* differs from the other rulespec_in*() routines in that it also
|
||||
* calls ioctl() for the rules, since it is impractical (and not very
|
||||
* useful) to return a list (or array) of rules, just so the caller
|
||||
* can call call ioctl() for each of them.
|
||||
*/
|
||||
static void
|
||||
rulespec_infp(FILE *fp, int cmd, devfs_rsnum rsnum)
|
||||
{
|
||||
struct devfs_rule dr;
|
||||
char *line;
|
||||
int rv;
|
||||
|
||||
assert(fp == stdin); /* XXX: De-hardcode "stdin" from error msg. */
|
||||
while (efgetln(fp, &line)) {
|
||||
rulespec_instr(&dr, line, rsnum);
|
||||
rv = ioctl(mpfd, cmd, &dr);
|
||||
if (rv == -1)
|
||||
err(1, "ioctl");
|
||||
free(line); /* efgetln() always malloc()s. */
|
||||
}
|
||||
if (ferror(stdin))
|
||||
err(1, "stdin");
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a /struct devfs_rule/ from a string.
|
||||
*/
|
||||
static void
|
||||
rulespec_instr(struct devfs_rule *dr, const char *str, devfs_rsnum rsnum)
|
||||
{
|
||||
char **av;
|
||||
int ac;
|
||||
|
||||
tokenize(str, &ac, &av);
|
||||
if (ac == 0)
|
||||
errx(1, "unexpected end of rulespec");
|
||||
rulespec_intok(dr, ac, av, rsnum);
|
||||
free(av[0]);
|
||||
free(av);
|
||||
}
|
||||
|
||||
/*
|
||||
* Construct a /struct devfs_rule/ from ac and av.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user