summaryrefslogtreecommitdiff
path: root/usr.sbin/config/sem.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/config/sem.c')
-rw-r--r--usr.sbin/config/sem.c326
1 files changed, 252 insertions, 74 deletions
diff --git a/usr.sbin/config/sem.c b/usr.sbin/config/sem.c
index d0a69b5bfb1..cdd67f47e42 100644
--- a/usr.sbin/config/sem.c
+++ b/usr.sbin/config/sem.c
@@ -1,7 +1,7 @@
-/* $OpenBSD: sem.c,v 1.2 1996/03/25 15:55:13 niklas Exp $ */
-/* $NetBSD: sem.c,v 1.2 1996/03/03 17:28:37 thorpej Exp $ */
+/* $OpenBSD: sem.c,v 1.3 1996/04/21 23:40:25 deraadt Exp $ */
+/* $NetBSD: sem.c,v 1.8 1996/03/17 21:12:03 cgd Exp $ */
-/*
+/*
* Copyright (c) 1992, 1993
* The Regents of the University of California. All rights reserved.
*
@@ -69,7 +69,9 @@ static struct hashtab *devitab; /* etc */
static struct attr errattr;
static struct devbase errdev;
+static struct deva errdeva;
static struct devbase **nextbase;
+static struct deva **nextdeva;
static struct config **nextcf;
static struct devi **nextdevi;
static struct devi **nextpseudo;
@@ -85,7 +87,7 @@ static struct devi *newdevi __P((const char *, int, struct devbase *d));
static struct devi *getdevi __P((const char *));
static const char *concat __P((const char *, int));
static int split __P((const char *, size_t, char *, size_t, int *));
-static void selectbase __P((struct devbase *));
+static void selectbase __P((struct devbase *, struct deva *));
static int onlist __P((struct nvlist *, void *));
static const char **fixloc __P((const char *, struct attr *, struct nvlist *));
@@ -99,6 +101,9 @@ initsem()
allbases = NULL;
nextbase = &allbases;
+ alldevas = NULL;
+ nextdeva = &alldevas;
+
cfhashtab = ht_new();
allcf = NULL;
nextcf = &allcf;
@@ -238,21 +243,19 @@ addtoattr(l, dev)
{
register struct nvlist *n;
- n = newnv(NULL, NULL, dev, 0);
- n->nv_next = l;
+ n = newnv(NULL, NULL, dev, 0, l);
return (n);
}
/*
- * Device a device, giving its allowable parent attachments, if any.
- * This may (or may not) also define an interface attribute and/or refer
- * to existing attributes. There may be a list of vectors.
+ * Define a device. This may (or may not) also define an interface
+ * attribute and/or refer to existing attributes.
*/
void
-defdev(dev, ispseudo, atlist, vectors, loclist, attrs)
+defdev(dev, ispseudo, loclist, attrs)
register struct devbase *dev;
int ispseudo;
- struct nvlist *atlist, *vectors, *loclist, *attrs;
+ struct nvlist *loclist, *attrs;
{
register struct nvlist *nv;
register struct attr *a;
@@ -278,40 +281,15 @@ defdev(dev, ispseudo, atlist, vectors, loclist, attrs)
loclist = NULL; /* defattr disposes of them for us */
if (defattr(dev->d_name, nv))
goto bad;
- nv = newnv(dev->d_name, NULL, getattr(dev->d_name), 0);
- nv->nv_next = attrs;
- attrs = nv;
+ attrs = newnv(dev->d_name, NULL, getattr(dev->d_name), 0,
+ attrs);
}
/* Committed! Set up fields. */
dev->d_ispseudo = ispseudo;
- dev->d_atlist = atlist;
- dev->d_vectors = vectors;
dev->d_attrs = attrs;
/*
- * Turn the `at' list into interface attributes (map each
- * nv_name to an attribute, or to NULL for root), and add
- * this device to those attributes, so that children can
- * be listed at this particular device if they are supported
- * by that attribute.
- */
- for (nv = atlist; nv != NULL; nv = nv->nv_next) {
- if (nv->nv_name == NULL) {
- nv->nv_ptr = NULL; /* at root */
- continue;
- }
- nv->nv_ptr = a = getattr(nv->nv_name);
- if (a == &errattr)
- continue; /* already complained */
- if (!a->a_iattr)
- error("%s cannot be at plain attribute `%s'",
- dev->d_name, a->a_name);
- else
- a->a_devs = addtoattr(a->a_devs, dev);
- }
-
- /*
* For each interface attribute this device refers to, add this
* device to its reference list. This makes, e.g., finding all
* "scsi"s easier.
@@ -323,8 +301,6 @@ defdev(dev, ispseudo, atlist, vectors, loclist, attrs)
}
return;
bad:
- nvfreel(atlist);
- nvfreel(vectors);
nvfreel(loclist);
nvfreel(attrs);
}
@@ -359,11 +335,11 @@ badname:
dev->d_next = NULL;
dev->d_isdef = 0;
dev->d_major = NODEV;
- dev->d_atlist = NULL;
- dev->d_vectors = NULL;
dev->d_attrs = NULL;
dev->d_ihead = NULL;
dev->d_ipp = &dev->d_ihead;
+ dev->d_ahead = NULL;
+ dev->d_app = &dev->d_ahead;
dev->d_umax = 0;
*nextbase = dev;
nextbase = &dev->d_next;
@@ -374,6 +350,143 @@ badname:
}
/*
+ * Define some of a device's allowable parent attachments.
+ * There may be a list of vectors and a list of (plain) attributes.
+ */
+void
+defdevattach(deva, dev, atlist, vectors, attrs)
+ register struct deva *deva;
+ struct devbase *dev;
+ struct nvlist *atlist, *vectors, *attrs;
+{
+ register struct nvlist *nv;
+ register struct attr *a;
+ register struct deva *da;
+
+ if (dev == &errdev)
+ goto bad;
+ if (deva == NULL)
+ deva = getdevattach(dev->d_name);
+ if (deva == &errdeva)
+ goto bad;
+ if (!dev->d_isdef) {
+ error("attaching undefined device `%s'", dev->d_name);
+ goto bad;
+ }
+ if (deva->d_isdef) {
+ error("redefinition of `%s'", deva->d_name);
+ goto bad;
+ }
+ if (dev->d_ispseudo) {
+ error("pseudo-devices can't attach");
+ goto bad;
+ }
+
+ deva->d_isdef = 1;
+ if (has_errobj(attrs, &errattr))
+ goto bad;
+ for (nv = attrs; nv != NULL; nv = nv->nv_next) {
+ a = nv->nv_ptr;
+ if (a == &errattr)
+ continue; /* already complained */
+ if (a->a_iattr)
+ error("`%s' is not a plain attribute", a->a_name);
+ }
+
+ /* Committed! Set up fields. */
+ deva->d_attrs = attrs;
+ deva->d_atlist = atlist;
+ deva->d_vectors = vectors;
+ deva->d_devbase = dev;
+
+ /*
+ * Turn the `at' list into interface attributes (map each
+ * nv_name to an attribute, or to NULL for root), and add
+ * this device to those attributes, so that children can
+ * be listed at this particular device if they are supported
+ * by that attribute.
+ */
+ for (nv = atlist; nv != NULL; nv = nv->nv_next) {
+ if (nv->nv_name == NULL)
+ nv->nv_ptr = a = NULL; /* at root */
+ else
+ nv->nv_ptr = a = getattr(nv->nv_name);
+ if (a == &errattr)
+ continue; /* already complained */
+
+ /*
+ * Make sure that an attachment spec doesn't
+ * already say how to attach to this attribute.
+ */
+ for (da = dev->d_ahead; da != NULL; da = da->d_bsame)
+ if (onlist(da->d_atlist, a))
+ error("attach at `%s' already done by `%s'",
+ a ? a->a_name : "root", da->d_name);
+
+ if (a == NULL)
+ continue; /* at root; don't add */
+ if (!a->a_iattr)
+ error("%s cannot be at plain attribute `%s'",
+ dev->d_name, a->a_name);
+ else
+ a->a_devs = addtoattr(a->a_devs, dev);
+ }
+
+ /* attach to parent */
+ *dev->d_app = deva;
+ dev->d_app = &deva->d_bsame;
+ return;
+bad:
+ nvfreel(atlist);
+ nvfreel(vectors);
+ nvfreel(attrs);
+}
+
+/*
+ * Look up a device attachment. Also makes sure it is a reasonable
+ * name, i.e., does not contain digits or special characters.
+ */
+struct deva *
+getdevattach(name)
+ const char *name;
+{
+ register u_char *p;
+ register struct deva *deva;
+
+ p = (u_char *)name;
+ if (!isalpha(*p))
+ goto badname;
+ while (*++p) {
+ if (!isalnum(*p) && *p != '_')
+ goto badname;
+ }
+ if (isdigit(*--p)) {
+badname:
+ error("bad device attachment name `%s'", name);
+ return (&errdeva);
+ }
+ deva = ht_lookup(devatab, name);
+ if (deva == NULL) {
+ deva = emalloc(sizeof *deva);
+ deva->d_name = name;
+ deva->d_next = NULL;
+ deva->d_bsame = NULL;
+ deva->d_isdef = 0;
+ deva->d_devbase = NULL;
+ deva->d_atlist = NULL;
+ deva->d_vectors = NULL;
+ deva->d_attrs = NULL;
+ deva->d_ihead = NULL;
+ deva->d_ipp = &deva->d_ihead;
+ *nextdeva = deva;
+ nextdeva = &deva->d_next;
+ if (ht_insert(devatab, name, deva))
+ panic("getdeva(%s)", name);
+ }
+ return (deva);
+}
+
+/*
* Look up an attribute.
*/
struct attr *
@@ -421,7 +534,7 @@ exclude(nv, name, what)
return (0);
}
-/*
+/*
* Map things like "ra0b" => makedev(major("ra"), 0*maxpartitions + 'b'-'a').
* Handle the case where the device number is given but there is no
* corresponding name, and map NULL to the default.
@@ -453,7 +566,7 @@ resolve(nvp, name, what, dflt, part)
min = (minor(dflt->nv_int) / maxpartitions) + part;
d = makedev(maj, min);
}
- *nvp = nv = newnv(NULL, NULL, NULL, d);
+ *nvp = nv = newnv(NULL, NULL, NULL, d, NULL);
}
if (nv->nv_int != NODEV) {
/*
@@ -607,10 +720,12 @@ newdevi(name, unit, d)
i->i_base = d;
i->i_next = NULL;
i->i_bsame = NULL;
+ i->i_asame = NULL;
i->i_alias = NULL;
i->i_at = NULL;
i->i_atattr = NULL;
i->i_atdev = NULL;
+ i->i_atdeva = NULL;
i->i_locs = NULL;
i->i_cfflags = 0;
i->i_lineno = currentline();
@@ -634,11 +749,14 @@ adddev(name, at, loclist, flags)
register struct devbase *ib; /* i->i_base */
register struct devbase *ab; /* not NULL => at another dev */
register struct nvlist *nv;
+ register struct deva *iba; /* devbase attachment used */
const char *cp;
int atunit;
char atbuf[NAMESIZE];
+ int hit;
ab = NULL;
+ iba = NULL;
if (at == NULL) {
/* "at root" */
if ((i = getdevi(name)) == NULL)
@@ -649,7 +767,13 @@ adddev(name, at, loclist, flags)
* bother?). Make sure this device can be at root.
*/
ib = i->i_base;
- if (!onlist(ib->d_atlist, NULL)) {
+ hit = 0;
+ for (iba = ib->d_ahead; iba != NULL; iba = iba->d_bsame)
+ if (onlist(iba->d_atlist, NULL)) {
+ hit = 1;
+ break;
+ }
+ if (!hit) {
error("%s's cannot attach to the root", ib->d_name);
goto bad;
}
@@ -664,38 +788,78 @@ adddev(name, at, loclist, flags)
goto bad;
ib = i->i_base;
cp = intern(atbuf);
- if ((attr = ht_lookup(attrtab, cp)) == NULL) {
- /*
- * Have to work a bit harder to see whether we have
- * something like "tg0 at esp0" (where esp is merely
- * not an attribute) or "tg0 at nonesuch0" (where
- * nonesuch is not even a device).
- */
- if ((ab = ht_lookup(devbasetab, cp)) == NULL) {
- error("%s at %s: `%s' unknown",
- name, at, atbuf);
- goto bad;
- }
- /*
- * See if the named parent carries an attribute
- * that allows it to supervise device ib.
- */
- for (nv = ab->d_attrs; nv != NULL; nv = nv->nv_next) {
- attr = nv->nv_ptr;
- if (onlist(attr->a_devs, ib))
- goto ok;
- }
- attr = &errattr;/* now onlist below will fail */
- }
- if (!onlist(attr->a_devs, ib)) {
- error("%s's cannot attach to %s's", ib->d_name, atbuf);
+
+ /*
+ * Devices can attach to two types of things: Attributes,
+ * and other devices (which have the appropriate attributes
+ * to allow attachment).
+ *
+ * (1) If we're attached to an attribute, then we don't need
+ * look at the parent base device to see what attributes
+ * it has, and make sure that we can attach to them.
+ *
+ * (2) If we're attached to a real device (i.e. named in
+ * the config file), we want to remember that so that
+ * at cross-check time, if the device we're attached to
+ * is missing but other devices which also provide the
+ * attribute are present, we don't get a false "OK."
+ *
+ * (3) If the thing we're attached to is an attribute
+ * but is actually named in the config file, we still
+ * have to remember its devbase.
+ */
+
+ /* Figure out parent's devbase, to satisfy case (3). */
+ ab = ht_lookup(devbasetab, cp);
+
+ /* Find out if it's an attribute. */
+ attr = ht_lookup(attrtab, cp);
+
+ /* Make sure we're _really_ attached to the attr. Case (1). */
+ if (attr != NULL && onlist(attr->a_devs, ib))
+ goto findattachment;
+
+ /*
+ * Else a real device, and not just an attribute. Case (2).
+ *
+ * Have to work a bit harder to see whether we have
+ * something like "tg0 at esp0" (where esp is merely
+ * not an attribute) or "tg0 at nonesuch0" (where
+ * nonesuch is not even a device).
+ */
+ if (ab == NULL) {
+ error("%s at %s: `%s' unknown",
+ name, at, atbuf);
goto bad;
}
+
+ /*
+ * See if the named parent carries an attribute
+ * that allows it to supervise device ib.
+ */
+ for (nv = ab->d_attrs; nv != NULL; nv = nv->nv_next) {
+ attr = nv->nv_ptr;
+ if (onlist(attr->a_devs, ib))
+ goto findattachment;
+ }
+ error("%s's cannot attach to %s's", ib->d_name, atbuf);
+ goto bad;
+
+findattachment:
+ /* find out which attachment it uses */
+ hit = 0;
+ for (iba = ib->d_ahead; iba != NULL; iba = iba->d_bsame)
+ if (onlist(iba->d_atlist, attr)) {
+ hit = 1;
+ break;
+ }
+ if (!hit)
+ panic("adddev: can't figure out attachment");
}
ok:
if ((i->i_locs = fixloc(name, attr, loclist)) == NULL)
goto bad;
- if (i->i_unit == STAR && ib->d_vectors != NULL) {
+ if (i->i_unit == STAR && iba->d_vectors != NULL) {
error("%s's cannot be *'d as they have preset vectors",
ib->d_name);
goto bad;
@@ -703,9 +867,14 @@ ok:
i->i_at = at;
i->i_atattr = attr;
i->i_atdev = ab;
+ i->i_atdeva = iba;
i->i_atunit = atunit;
i->i_cfflags = flags;
- selectbase(ib);
+
+ *iba->d_ipp = i;
+ iba->d_ipp = &i->i_asame;
+
+ selectbase(ib, iba);
/* all done, fall into ... */
bad:
nvfreel(loclist);
@@ -736,7 +905,7 @@ addpseudo(name, number)
i = newdevi(name, number - 1, d); /* foo 16 => "foo0..foo15" */
if (ht_insert(devitab, name, i))
panic("addpseudo(%s)", name);
- selectbase(d);
+ selectbase(d, NULL);
*nextpseudo = i;
nextpseudo = &i->i_next;
npseudo++;
@@ -863,8 +1032,9 @@ split(name, nlen, base, bsize, aunit)
* attributes for "optional foo".
*/
static void
-selectbase(d)
+selectbase(d, da)
register struct devbase *d;
+ register struct deva *da;
{
register struct attr *a;
register struct nvlist *nv;
@@ -874,6 +1044,14 @@ selectbase(d)
a = nv->nv_ptr;
(void)ht_insert(selecttab, a->a_name, (char *)a->a_name);
}
+ if (da != NULL) {
+ (void)ht_insert(selecttab, da->d_name, (char *)da->d_name);
+ for (nv = da->d_attrs; nv != NULL; nv = nv->nv_next) {
+ a = nv->nv_ptr;
+ (void)ht_insert(selecttab, a->a_name,
+ (char *)a->a_name);
+ }
+ }
}
/*