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
|
For example, a rule can be written that sets the GID to
|
||||||
.Li games
|
.Li games
|
||||||
for all devices with major number 53.
|
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
|
.Pp
|
||||||
The following conditions are recognized.
|
The following conditions are recognized.
|
||||||
Conditions are ANDed together when matching a device;
|
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:
|
Since hiding all nodes isn't very useful, we can undo like so:
|
||||||
.Pp
|
.Pp
|
||||||
.Dl devfs rule apply unhide
|
.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
|
.Sh SEE ALSO
|
||||||
.Xr jail 2 ,
|
.Xr jail 2 ,
|
||||||
.Xr glob 3 ,
|
.Xr glob 3 ,
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*-
|
/*-
|
||||||
* Copyright (c) 2002 Dima Dorfman.
|
* Copyright (c) 2001, 2002 Dima Dorfman.
|
||||||
* All rights reserved.
|
* All rights reserved.
|
||||||
*
|
*
|
||||||
* Redistribution and use in source and binary forms, with or without
|
* Redistribution and use in source and binary forms, with or without
|
||||||
@ -32,7 +32,9 @@
|
|||||||
__FBSDID("$FreeBSD$");
|
__FBSDID("$FreeBSD$");
|
||||||
|
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
|
#include <sys/queue.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <paths.h>
|
#include <paths.h>
|
||||||
@ -131,6 +133,93 @@ eatonum(const char *s)
|
|||||||
return (num);
|
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
|
void
|
||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
|
@ -48,6 +48,8 @@ command_t rule_main, ruleset_main;
|
|||||||
int atonum(const char *, uint16_t *);
|
int atonum(const char *, uint16_t *);
|
||||||
int eatoi(const char *);
|
int eatoi(const char *);
|
||||||
uint16_t eatonum(const char *);
|
uint16_t eatonum(const char *);
|
||||||
|
size_t efgetln(FILE *, char **);
|
||||||
|
void tokenize(const char *, int *, char ***);
|
||||||
void usage(void) __dead2;
|
void usage(void) __dead2;
|
||||||
|
|
||||||
extern int mpfd; /* Mount-point file descriptor. */
|
extern int mpfd; /* Mount-point file descriptor. */
|
||||||
|
@ -35,6 +35,7 @@ __FBSDID("$FreeBSD$");
|
|||||||
#include <sys/conf.h>
|
#include <sys/conf.h>
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
@ -46,6 +47,9 @@ __FBSDID("$FreeBSD$");
|
|||||||
|
|
||||||
#include "extern.h"
|
#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,
|
static void rulespec_intok(struct devfs_rule *dr, int ac, char **av,
|
||||||
devfs_rsnum rsnum);
|
devfs_rsnum rsnum);
|
||||||
static void rulespec_outfp(FILE *fp, struct devfs_rule *dr);
|
static void rulespec_outfp(FILE *fp, struct devfs_rule *dr);
|
||||||
@ -109,10 +113,14 @@ rule_add(int ac, char **av)
|
|||||||
|
|
||||||
if (ac < 2)
|
if (ac < 2)
|
||||||
usage();
|
usage();
|
||||||
rulespec_intok(&dr, ac - 1, av + 1, in_rsnum);
|
if (strcmp(av[1], "-") == 0)
|
||||||
rv = ioctl(mpfd, DEVFSIO_RADD, &dr);
|
rulespec_infp(stdin, DEVFSIO_RADD, in_rsnum);
|
||||||
if (rv == -1)
|
else {
|
||||||
err(1, "ioctl DEVFSIO_RADD");
|
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);
|
return (0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,10 +135,14 @@ rule_apply(int ac __unused, char **av __unused)
|
|||||||
if (ac < 2)
|
if (ac < 2)
|
||||||
usage();
|
usage();
|
||||||
if (!atonum(av[1], &rnum)) {
|
if (!atonum(av[1], &rnum)) {
|
||||||
rulespec_intok(&dr, ac - 1, av + 1, in_rsnum);
|
if (strcmp(av[1], "-") == 0)
|
||||||
rv = ioctl(mpfd, DEVFSIO_RAPPLY, &dr);
|
rulespec_infp(stdin, DEVFSIO_RAPPLY, in_rsnum);
|
||||||
if (rv == -1)
|
else {
|
||||||
err(1, "ioctl DEVFSIO_RAPPLY");
|
rulespec_intok(&dr, ac - 1, av + 1, in_rsnum);
|
||||||
|
rv = ioctl(mpfd, DEVFSIO_RAPPLY, &dr);
|
||||||
|
if (rv == -1)
|
||||||
|
err(1, "ioctl DEVFSIO_RAPPLY");
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
rid = mkrid(in_rsnum, rnum);
|
rid = mkrid(in_rsnum, rnum);
|
||||||
rv = ioctl(mpfd, DEVFSIO_RAPPLYID, &rid);
|
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.
|
* Construct a /struct devfs_rule/ from ac and av.
|
||||||
*/
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user