diff options
Diffstat (limited to 'usr.sbin/config/sem.c')
-rw-r--r-- | usr.sbin/config/sem.c | 326 |
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); + } + } } /* |