summaryrefslogtreecommitdiffstats
path: root/sbin
diff options
context:
space:
mode:
authordd <dd@FreeBSD.org>2002-07-28 06:45:30 +0000
committerdd <dd@FreeBSD.org>2002-07-28 06:45:30 +0000
commit833e15959ca59011b38b7cf26448e69e68f5e88e (patch)
treee20829cdf8b40d7cb5d79032332a8fc550d14ca7 /sbin
parente3d769e49372f3888a55479a68c112f27766aa23 (diff)
downloadFreeBSD-src-833e15959ca59011b38b7cf26448e69e68f5e88e.zip
FreeBSD-src-833e15959ca59011b38b7cf26448e69e68f5e88e.tar.gz
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.
Diffstat (limited to 'sbin')
-rw-r--r--sbin/devfs/devfs.826
-rw-r--r--sbin/devfs/devfs.c91
-rw-r--r--sbin/devfs/extern.h2
-rw-r--r--sbin/devfs/rule.c71
4 files changed, 181 insertions, 9 deletions
diff --git a/sbin/devfs/devfs.8 b/sbin/devfs/devfs.8
index 11cede3..b22a9ad 100644
--- a/sbin/devfs/devfs.8
+++ b/sbin/devfs/devfs.8
@@ -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 ,
diff --git a/sbin/devfs/devfs.c b/sbin/devfs/devfs.c
index 4622bb9..8608af3 100644
--- a/sbin/devfs/devfs.c
+++ b/sbin/devfs/devfs.c
@@ -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)
{
diff --git a/sbin/devfs/extern.h b/sbin/devfs/extern.h
index 9814b15..d2c38ac 100644
--- a/sbin/devfs/extern.h
+++ b/sbin/devfs/extern.h
@@ -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. */
diff --git a/sbin/devfs/rule.c b/sbin/devfs/rule.c
index 27ad2a6..9d2bd3d 100644
--- a/sbin/devfs/rule.c
+++ b/sbin/devfs/rule.c
@@ -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);
@@ -249,6 +261,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.
*/
static void
OpenPOWER on IntegriCloud