diff options
Diffstat (limited to 'usr.sbin/config')
-rw-r--r-- | usr.sbin/config/config.8 | 6 | ||||
-rw-r--r-- | usr.sbin/config/config.h | 66 | ||||
-rw-r--r-- | usr.sbin/config/files.c | 373 | ||||
-rw-r--r-- | usr.sbin/config/gram.y | 69 | ||||
-rw-r--r-- | usr.sbin/config/hash.c | 6 | ||||
-rw-r--r-- | usr.sbin/config/main.c | 104 | ||||
-rw-r--r-- | usr.sbin/config/mkheaders.c | 8 | ||||
-rw-r--r-- | usr.sbin/config/mkioconf.c | 33 | ||||
-rw-r--r-- | usr.sbin/config/mkmakefile.c | 60 | ||||
-rw-r--r-- | usr.sbin/config/mkswap.c | 10 | ||||
-rw-r--r-- | usr.sbin/config/pack.c | 6 | ||||
-rw-r--r-- | usr.sbin/config/scan.l | 8 | ||||
-rw-r--r-- | usr.sbin/config/sem.c | 326 | ||||
-rw-r--r-- | usr.sbin/config/sem.h | 9 | ||||
-rw-r--r-- | usr.sbin/config/util.c | 15 |
15 files changed, 804 insertions, 295 deletions
diff --git a/usr.sbin/config/config.8 b/usr.sbin/config/config.8 index b93276db33d..e8c8bac7e0b 100644 --- a/usr.sbin/config/config.8 +++ b/usr.sbin/config/config.8 @@ -1,5 +1,5 @@ -.\" $OpenBSD: config.8,v 1.2 1996/03/25 15:55:01 niklas Exp $ -.\" $NetBSD: config.8,v 1.8 1996/03/03 17:28:05 thorpej Exp $ +.\" $OpenBSD: config.8,v 1.3 1996/04/21 23:40:05 deraadt Exp $ +.\" $NetBSD: config.8,v 1.9 1996/03/17 06:29:19 cgd Exp $ .\" .\" Copyright (c) 1980, 1991, 1993 .\" The Regents of the University of California. All rights reserved. @@ -53,7 +53,7 @@ program. .\"used on the SPARC and i386 platforms. .\"The old version of config is still used with the .\"HP300, DECstation, and derivative platforms. -.\"Only the version of +.\"Only the version of .\".Nm config .\"applicable to the architecture that you are running .\"will be installed on your machine. diff --git a/usr.sbin/config/config.h b/usr.sbin/config/config.h index 116503b51a8..178c6923741 100644 --- a/usr.sbin/config/config.h +++ b/usr.sbin/config/config.h @@ -1,5 +1,5 @@ -/* $OpenBSD: config.h,v 1.2 1996/03/25 15:55:02 niklas Exp $ */ -/* $NetBSD: config.h,v 1.19 1996/03/03 17:28:08 thorpej Exp $ */ +/* $OpenBSD: config.h,v 1.3 1996/04/21 23:40:07 deraadt Exp $ */ +/* $NetBSD: config.h,v 1.23 1996/03/17 13:18:15 cgd Exp $ */ /* * Copyright (c) 1992, 1993 @@ -94,19 +94,27 @@ struct attr { }; /* - * The "base" part of a device ("uba", "sd"; but not "uba2" or - * "sd0"). It may be found "at" one or more attributes, including - * "at root" (this is represented by a NULL attribute). + * The "base" part (struct devbase) of a device ("uba", "sd"; but not + * "uba2" or "sd0"). It may be found "at" one or more attributes, + * including "at root" (this is represented by a NULL attribute), as + * specified by the device attachments (struct deva). * * Each device may also export attributes. If any provide an output * interface (e.g., "esp" provides "scsi"), other devices (e.g., * "tg"s) can be found at instances of this one (e.g., "esp"s). * Such a connection must provide locators as specified by that - * interface attribute (e.g., "target"). + * interface attribute (e.g., "target"). The base device can + * export both output (aka `interface') attributes, as well as + * import input (`plain') attributes. Device attachments may + * only import input attributes; it makes no sense to have a + * specific attachment export a new interface to other devices. * * Each base carries a list of instances (via d_ihead). Note that this * list "skips over" aliases; those must be found through the instances - * themselves. + * themselves. Each base also carries a list of possible attachments, + * each of which specify a set of devices that the device can attach + * to, as well as the device instances that are actually using that + * attachment. */ struct devbase { const char *d_name; /* e.g., "sd" */ @@ -114,12 +122,25 @@ struct devbase { int d_isdef; /* set once properly defined */ int d_ispseudo; /* is a pseudo-device */ int d_major; /* used for "root on sd0", e.g. */ + struct nvlist *d_attrs; /* attributes, if any */ + int d_umax; /* highest unit number + 1 */ + struct devi *d_ihead; /* first instance, if any */ + struct devi **d_ipp; /* used for tacking on more instances */ + struct deva *d_ahead; /* first attachment, if any */ + struct deva **d_app; /* used for tacking on attachments */ +}; + +struct deva { + const char *d_name; /* name of attachment, e.g. "com_isa" */ + struct deva *d_next; /* linked list */ + struct deva *d_bsame; /* list on same base */ + int d_isdef; /* set once properly defined */ + struct devbase *d_devbase; /* the base device */ struct nvlist *d_atlist; /* e.g., "at tg" (attr list) */ struct nvlist *d_vectors; /* interrupt vectors, if any */ struct nvlist *d_attrs; /* attributes, if any */ struct devi *d_ihead; /* first instance, if any */ struct devi **d_ipp; /* used for tacking on more instances */ - int d_umax; /* highest unit number + 1 */ }; /* @@ -139,10 +160,12 @@ struct devi { struct devbase *i_base;/* e.g., pointer to "sd" base */ struct devi *i_next; /* list of all instances */ struct devi *i_bsame; /* list on same base */ + struct devi *i_asame; /* list on same base attachment */ struct devi *i_alias; /* other aliases of this instance */ const char *i_at; /* where this is "at" (NULL if at root) */ struct attr *i_atattr; /* attr that allowed attach */ - struct devbase *i_atdev;/* dev if "at <devname><unit>", else NULL */ + struct devbase *i_atdev;/* if "at <devname><unit>", else NULL */ + struct deva *i_atdeva; const char **i_locs; /* locators (as given by i_atattr) */ int i_atunit; /* unit from "at" */ int i_cfflags; /* flags from config line */ @@ -165,7 +188,16 @@ struct devi { /* * Files. Each file is either standard (always included) or optional, - * depending on whether it has names on which to *be* optional. + * depending on whether it has names on which to *be* optional. The + * options field (fi_optx) is actually an expression tree, with nodes + * for OR, AND, and NOT, as well as atoms (words) representing some + * particular option. The node type is stored in the nv_int field. + * Subexpressions appear in the `next' field; for the binary operators + * AND and OR, the left subexpression is first stored in the nv_ptr field. + * + * For any file marked as needs-count or needs-flag, fixfiles() will + * build fi_optf, a `flat list' of the options with nv_int fields that + * contain counts or `need' flags; this is used in mkheaders(). */ struct files { struct files *fi_next; /* linked list */ @@ -176,9 +208,14 @@ struct files { const char *fi_path; /* full file path */ const char *fi_tail; /* name, i.e., rindex(fi_path, '/') + 1 */ const char *fi_base; /* tail minus ".c" (or whatever) */ - struct nvlist *fi_opt; /* optional on ... */ + struct nvlist *fi_optx;/* options expression */ + struct nvlist *fi_optf;/* flattened version of above, if needed */ const char *fi_mkrule; /* special make rule, if any */ }; +#define FX_ATOM 0 /* atom (in nv_name) */ +#define FX_NOT 1 /* NOT expr (subexpression in nv_next) */ +#define FX_AND 2 /* AND expr (lhs in nv_ptr, rhs in nv_next) */ +#define FX_OR 3 /* OR expr (lhs in nv_ptr, rhs in nv_next) */ /* flags */ #define FI_SEL 0x01 /* selected */ @@ -210,10 +247,12 @@ int maxpartitions; /* configuration's "maxpartitions" parameter */ struct nvlist *options; /* options */ struct nvlist *mkoptions; /* makeoptions */ struct hashtab *devbasetab; /* devbase lookup */ +struct hashtab *devatab; /* devbase attachment lookup */ struct hashtab *selecttab; /* selects things that are "optional foo" */ struct hashtab *needcnttab; /* retains names marked "needs-count" */ struct devbase *allbases; /* list of all devbase structures */ +struct deva *alldevas; /* list of all devbase attachment structures */ struct config *allcf; /* list of configured kernels */ struct devi *alldevi; /* list of all instances */ struct devi *allpseudo; /* list of all pseudo-devices */ @@ -252,6 +291,8 @@ const char *intern __P((const char *)); /* main.c */ void addoption __P((const char *name, const char *value)); void addmkoption __P((const char *name, const char *value)); +int devbase_has_instances __P((struct devbase *, int)); +int deva_has_instances __P((struct deva *, int)); /* mkheaders.c */ int mkheaders __P((void)); @@ -281,6 +322,7 @@ char *path __P((const char *)); void error __P((const char *, ...)); /* immediate errs */ void xerror __P((const char *, int, const char *, ...)); /* delayed errs */ __dead void panic __P((const char *, ...)); -struct nvlist *newnv __P((const char *, const char *, void *, int)); +struct nvlist *newnv __P((const char *, const char *, void *, int, + struct nvlist *)); void nvfree __P((struct nvlist *)); void nvfreel __P((struct nvlist *)); diff --git a/usr.sbin/config/files.c b/usr.sbin/config/files.c index 61574f5b004..ac2f302cf51 100644 --- a/usr.sbin/config/files.c +++ b/usr.sbin/config/files.c @@ -1,7 +1,7 @@ -/* $OpenBSD: files.c,v 1.3 1996/03/25 15:55:03 niklas Exp $ */ -/* $NetBSD: files.c,v 1.3 1996/03/03 17:28:10 thorpej Exp $ */ +/* $OpenBSD: files.c,v 1.4 1996/04/21 23:40:09 deraadt Exp $ */ +/* $NetBSD: files.c,v 1.6 1996/03/17 13:18:17 cgd Exp $ */ -/* +/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -66,6 +66,14 @@ static struct hashtab *pathtab; /* full path names */ static struct files **nextfile; static struct files **unchecked; +static int checkaux __P((const char *, void *)); +static int fixcount __P((const char *, void *)); +static int fixfsel __P((const char *, void *)); +static int fixsel __P((const char *, void *)); +static int expr_eval __P((struct nvlist *, + int (*)(const char *, void *), void *)); +static void expr_free __P((struct nvlist *)); + void initfiles() { @@ -88,17 +96,17 @@ showprev(pref, fi) } void -addfile(path, opts, flags, rule) +addfile(path, optx, flags, rule) const char *path; - struct nvlist *opts; + struct nvlist *optx; int flags; const char *rule; { struct files *fi; - const char *base, *dotp, *tail; + const char *dotp, *tail; size_t baselen; int needc, needf; - char buf[200]; + char base[200]; /* check various errors */ needc = flags & FI_NEEDSCOUNT; @@ -107,15 +115,10 @@ addfile(path, opts, flags, rule) error("cannot mix needs-count and needs-flag"); goto bad; } - if (opts == NULL && (needc || needf)) { + if (optx == NULL && (needc || needf)) { error("nothing to %s for %s", needc ? "count" : "flag", path); goto bad; } - if ((fi = ht_lookup(pathtab, path)) != NULL) { - showprev("", fi); - error("file %s listed again", path); - goto bad; - } /* find last part of pathname, and same without trailing suffix */ tail = rindex(path, '/'); @@ -125,57 +128,41 @@ addfile(path, opts, flags, rule) tail++; dotp = rindex(tail, '.'); if (dotp == NULL || dotp[1] == 0 || - (baselen = dotp - tail) >= sizeof(buf)) { + (baselen = dotp - tail) >= sizeof(base)) { error("invalid pathname `%s'", path); goto bad; } /* - * Make a copy of the path without the .c/.s/whatever suffix. - * This must be unique per "files" file (e.g., a specific - * file can override a standard file, but no standard file - * can override another standard file). This is not perfect - * but should catch any major errors. - */ - bcopy(tail, buf, baselen); - buf[baselen] = 0; - base = intern(buf); - if ((fi = ht_lookup(basetab, base)) != NULL) { - if (fi->fi_srcfile != yyfile) { - showprev("note: ", fi); - error("is overridden by %s", path); - errors--; /* take it away */ - fi->fi_flags |= FI_HIDDEN; - } else { - showprev("", fi); - error("collides with %s (both make %s.o)", - path, base); - goto bad; - } - } - - /* - * Commit this file to memory. + * Commit this file to memory. We will decide later whether it + * will be used after all. */ fi = emalloc(sizeof *fi); + if (ht_insert(pathtab, path, fi)) { + free(fi); + if ((fi = ht_lookup(pathtab, path)) == NULL) + panic("addfile: ht_lookup(%s)", path); + error("duplicate file %s", path); + xerror(fi->fi_srcfile, fi->fi_srcline, + "here is the original definition"); + } + memcpy(base, tail, baselen); + base[baselen] = 0; fi->fi_next = NULL; fi->fi_srcfile = yyfile; fi->fi_srcline = currentline(); fi->fi_flags = flags; - fi->fi_lastc = dotp[strlen(dotp) - 1]; fi->fi_path = path; fi->fi_tail = tail; - fi->fi_base = base; - fi->fi_opt = opts; + fi->fi_base = intern(base); + fi->fi_optx = optx; + fi->fi_optf = NULL; fi->fi_mkrule = rule; - if (ht_insert(pathtab, path, fi)) - panic("addfile: ht_insert(%s)", path); - (void)ht_replace(basetab, base, fi); *nextfile = fi; nextfile = &fi->fi_next; return; bad: - nvfreel(opts); + expr_free(optx); } /* @@ -191,75 +178,265 @@ checkfiles() register struct nvlist *nv; last = NULL; - for (fi = *unchecked; fi != NULL; last = fi, fi = fi->fi_next) { - if ((fi->fi_flags & FI_NEEDSCOUNT) == 0) - continue; - for (nv = fi->fi_opt; nv != NULL; nv = nv->nv_next) - if (ht_lookup(devbasetab, nv->nv_name) == NULL) { - xerror(fi->fi_srcfile, fi->fi_srcline, - "`%s' is not a countable device", - nv->nv_name); - /* keep fixfiles() from complaining again */ - fi->fi_flags |= FI_HIDDEN; - } - } + for (fi = *unchecked; fi != NULL; last = fi, fi = fi->fi_next) + if ((fi->fi_flags & FI_NEEDSCOUNT) != 0) + (void)expr_eval(fi->fi_optx, checkaux, fi); if (last != NULL) unchecked = &last->fi_next; } /* + * Auxiliary function for checkfiles, called from expr_eval. + * We are not actually interested in the expression's value. + */ +static int +checkaux(name, context) + const char *name; + void *context; +{ + register struct files *fi = context; + + if (ht_lookup(devbasetab, name) == NULL) { + xerror(fi->fi_srcfile, fi->fi_srcline, + "`%s' is not a countable device", + name); + /* keep fixfiles() from complaining again */ + fi->fi_flags |= FI_HIDDEN; + } + return (0); +} + +/* * We have finished reading everything. Tack the files down: calculate - * selection and counts as needed. + * selection and counts as needed. Check that the object files built + * from the selected sources do not collide. */ int fixfiles() { - register struct files *fi; - register struct nvlist *nv; - register struct devbase *dev; - int sel, err; + register struct files *fi, *ofi; + struct nvlist *flathead, **flatp; + int err, sel; err = 0; for (fi = allfiles; fi != NULL; fi = fi->fi_next) { + /* Skip files that generated counted-device complaints. */ if (fi->fi_flags & FI_HIDDEN) continue; - if ((nv = fi->fi_opt) == NULL) { /* standard */ - fi->fi_flags |= FI_SEL; - continue; + if (fi->fi_optx != NULL) { + /* Optional: see if it is to be included. */ + flathead = NULL; + flatp = &flathead; + sel = expr_eval(fi->fi_optx, + fi->fi_flags & FI_NEEDSCOUNT ? fixcount : + fi->fi_flags & FI_NEEDSFLAG ? fixfsel : + fixsel, + &flatp); + fi->fi_optf = flathead; + if (!sel) + continue; } - /* figure out whether it is selected */ - sel = 0; - if (fi->fi_flags & FI_NEEDSCOUNT) { - /* ... and compute counts too */ - do { - dev = ht_lookup(devbasetab, nv->nv_name); - if (dev == NULL) { - xerror(fi->fi_srcfile, fi->fi_srcline, - "`%s' is not a countable device", - nv->nv_name); - err = 1; - } else { - if (dev->d_umax) - sel = 1; - nv->nv_int = dev->d_umax; - (void)ht_insert(needcnttab, - nv->nv_name, nv); - } - } while ((nv = nv->nv_next) != NULL); - } else { - do { - if (ht_lookup(selecttab, nv->nv_name)) { - sel = 1; - break; - } - } while ((nv = nv->nv_next) != NULL); - if (fi->fi_flags & FI_NEEDSFLAG) - for (nv = fi->fi_opt; nv; nv = nv->nv_next) - nv->nv_int = sel; + + /* We like this file. Make sure it generates a unique .o. */ + if (ht_insert(basetab, fi->fi_base, fi)) { + if ((ofi = ht_lookup(basetab, fi->fi_base)) == NULL) + panic("fixfiles ht_lookup(%s)", fi->fi_base); + /* + * If the new file comes from a different source, + * allow the new one to override the old one. + */ + if (fi->fi_path != ofi->fi_path) { + if (ht_replace(basetab, fi->fi_base, fi) != 1) + panic("fixfiles ht_replace(%s)", + fi->fi_base); + ofi->fi_flags &= ~FI_SEL; + ofi->fi_flags |= FI_HIDDEN; + } else { + xerror(fi->fi_srcfile, fi->fi_srcline, + "object file collision on %s.o, from %s", + fi->fi_base, fi->fi_path); + xerror(ofi->fi_srcfile, ofi->fi_srcline, + "here is the previous file: %s", + ofi->fi_path); + err = 1; + } } - /* if selected, we are go */ - if (sel) - fi->fi_flags |= FI_SEL; + fi->fi_flags |= FI_SEL; } return (err); } + +/* + * Called when evaluating a needs-count expression. Make sure the + * atom is a countable device. The expression succeeds iff there + * is at least one of them (note that while `xx*' will not always + * set xx's d_umax > 0, you cannot mix '*' and needs-count). The + * mkheaders() routine wants a flattened, in-order list of the + * atoms for `#define name value' lines, so we build that as we + * are called to eval each atom. + */ +static int +fixcount(name, context) + register const char *name; + void *context; +{ + register struct nvlist ***p = context; + register struct devbase *dev; + register struct nvlist *nv; + + dev = ht_lookup(devbasetab, name); + if (dev == NULL) /* cannot occur here; we checked earlier */ + panic("fixcount(%s)", name); + nv = newnv(name, NULL, NULL, dev->d_umax, NULL); + **p = nv; + *p = &nv->nv_next; + (void)ht_insert(needcnttab, name, nv); + return (dev->d_umax != 0); +} + +/* + * Called from fixfiles when eval'ing a selection expression for a + * file that will generate a .h with flags. We will need the flat list. + */ +static int +fixfsel(name, context) + const char *name; + void *context; +{ + register struct nvlist ***p = context; + register struct nvlist *nv; + register int sel; + + sel = ht_lookup(selecttab, name) != NULL; + nv = newnv(name, NULL, NULL, sel, NULL); + **p = nv; + *p = &nv->nv_next; + return (sel); +} + +/* + * As for fixfsel above, but we do not need the flat list. + */ +static int +fixsel(name, context) + const char *name; + void *context; +{ + + return (ht_lookup(selecttab, name) != NULL); +} + +/* + * Eval an expression tree. Calls the given function on each node, + * passing it the given context & the name; return value is &/|/! of + * results of evaluating atoms. + * + * No short circuiting ever occurs. fn must return 0 or 1 (otherwise + * our mixing of C's bitwise & boolean here may give surprises). + */ +static int +expr_eval(expr, fn, context) + register struct nvlist *expr; + register int (*fn) __P((const char *, void *)); + register void *context; +{ + int lhs, rhs; + + switch (expr->nv_int) { + + case FX_ATOM: + return ((*fn)(expr->nv_name, context)); + + case FX_NOT: + return (!expr_eval(expr->nv_next, fn, context)); + + case FX_AND: + lhs = expr_eval(expr->nv_ptr, fn, context); + rhs = expr_eval(expr->nv_next, fn, context); + return (lhs & rhs); + + case FX_OR: + lhs = expr_eval(expr->nv_ptr, fn, context); + rhs = expr_eval(expr->nv_next, fn, context); + return (lhs | rhs); + } + panic("expr_eval %d", expr->nv_int); + /* NOTREACHED */ +} + +/* + * Free an expression tree. + */ +static void +expr_free(expr) + register struct nvlist *expr; +{ + register struct nvlist *rhs; + + /* This loop traverses down the RHS of each subexpression. */ + for (; expr != NULL; expr = rhs) { + switch (expr->nv_int) { + + /* Atoms and !-exprs have no left hand side. */ + case FX_ATOM: + case FX_NOT: + break; + + /* For AND and OR nodes, free the LHS. */ + case FX_AND: + case FX_OR: + expr_free(expr->nv_ptr); + break; + + default: + panic("expr_free %d", expr->nv_int); + } + rhs = expr->nv_next; + nvfree(expr); + } +} + +#ifdef DEBUG +/* + * Print expression tree. + */ +void +prexpr(expr) + struct nvlist *expr; +{ + static void pr0(); + + printf("expr ="); + pr0(expr); + printf("\n"); + (void)fflush(stdout); +} + +static void +pr0(e) + register struct nvlist *e; +{ + + switch (e->nv_int) { + case FX_ATOM: + printf(" %s", e->nv_name); + return; + case FX_NOT: + printf(" (!"); + break; + case FX_AND: + printf(" (&"); + break; + case FX_OR: + printf(" (|"); + break; + default: + printf(" (?%d?", e->nv_int); + break; + } + if (e->nv_ptr) + pr0(e->nv_ptr); + pr0(e->nv_next); + printf(")"); +} +#endif diff --git a/usr.sbin/config/gram.y b/usr.sbin/config/gram.y index 3b197a85745..8d50756b2e3 100644 --- a/usr.sbin/config/gram.y +++ b/usr.sbin/config/gram.y @@ -1,6 +1,6 @@ %{ -/* $OpenBSD: gram.y,v 1.2 1996/03/25 15:55:04 niklas Exp $ */ -/* $NetBSD: gram.y,v 1.3 1996/03/03 17:28:13 thorpej Exp $ */ +/* $OpenBSD: gram.y,v 1.3 1996/04/21 23:40:11 deraadt Exp $ */ +/* $NetBSD: gram.y,v 1.7 1996/03/17 13:18:18 cgd Exp $ */ /* * Copyright (c) 1992, 1993 @@ -69,14 +69,21 @@ static struct config conf; /* at most one active at a time */ /* the following is used to recover nvlist space after errors */ static struct nvlist *alloc[1000]; static int adepth; -#define new0(n,s,p,i) (alloc[adepth++] = newnv(n, s, p, i)) -#define new_n(n) new0(n, NULL, NULL, 0) -#define new_ns(n, s) new0(n, s, NULL, 0) -#define new_si(s, i) new0(NULL, s, NULL, i) -#define new_nsi(n,s,i) new0(n, s, NULL, i) -#define new_np(n, p) new0(n, NULL, p, 0) -#define new_s(s) new0(NULL, s, NULL, 0) -#define new_p(p) new0(NULL, NULL, p, 0) +#define new0(n,s,p,i,x) (alloc[adepth++] = newnv(n, s, p, i, x)) +#define new_n(n) new0(n, NULL, NULL, 0, NULL) +#define new_nx(n, x) new0(n, NULL, NULL, 0, x) +#define new_ns(n, s) new0(n, s, NULL, 0, NULL) +#define new_si(s, i) new0(NULL, s, NULL, i, NULL) +#define new_nsi(n,s,i) new0(n, s, NULL, i, NULL) +#define new_np(n, p) new0(n, NULL, p, 0, NULL) +#define new_s(s) new0(NULL, s, NULL, 0, NULL) +#define new_p(p) new0(NULL, NULL, p, 0, NULL) +#define new_px(p, x) new0(NULL, NULL, p, 0, x) + +#define fx_atom(s) new0(s, NULL, NULL, FX_ATOM, NULL) +#define fx_not(e) new0(NULL, NULL, NULL, FX_NOT, e) +#define fx_and(e1, e2) new0(NULL, NULL, e1, FX_AND, e2) +#define fx_or(e1, e2) new0(NULL, NULL, e1, FX_OR, e2) static void cleanup __P((void)); static void setmachine __P((const char *, const char *)); @@ -87,22 +94,24 @@ static void setmaxpartitions __P((int)); %union { struct attr *attr; struct devbase *devb; + struct deva *deva; struct nvlist *list; const char *str; int val; } -%token AND AT COMPILE_WITH CONFIG DEFINE DEVICE DUMPS ENDFILE +%token AND AT ATTACH COMPILE_WITH CONFIG DEFINE DEVICE DUMPS ENDFILE %token XFILE FLAGS INCLUDE XMACHINE MAJOR MAKEOPTIONS MAXUSERS MAXPARTITIONS -%token MINOR ON OPTIONS PSEUDO_DEVICE ROOT SWAP VECTOR +%token MINOR ON OPTIONS PSEUDO_DEVICE ROOT SWAP VECTOR WITH %token <val> FFLAG NUMBER %token <str> PATHNAME WORD -%type <list> fopts +%type <list> fopts fexpr fatom %type <val> fflgs %type <str> rule %type <attr> attr %type <devb> devbase +%type <deva> devattach_opt %type <list> atlist interface_opt %type <str> atname %type <list> loclist_opt loclist locdef @@ -164,9 +173,19 @@ file: /* order of options is important, must use right recursion */ fopts: - WORD fopts = { ($$ = new_n($1))->nv_next = $2; } | + fexpr = { $$ = $1; } | /* empty */ = { $$ = NULL; }; +fexpr: + fatom = { $$ = $1; } | + '!' fatom = { $$ = fx_not($2); } | + fexpr '&' fexpr = { $$ = fx_and($1, $3); } | + fexpr '|' fexpr = { $$ = fx_or($1, $3); } | + '(' fexpr ')' = { $$ = $2; }; + +fatom: + WORD = { $$ = fx_atom($1); }; + fflgs: fflgs FFLAG = { $$ = $1 | $2; } | /* empty */ = { $$ = 0; }; @@ -194,14 +213,17 @@ one_def: file | include | DEFINE WORD interface_opt = { (void)defattr($2, $3); } | - DEVICE devbase AT atlist veclist_opt interface_opt attrs_opt - = { defdev($2, 0, $4, $5, $6, $7); } | + DEVICE devbase interface_opt attrs_opt + = { defdev($2, 0, $3, $4); } | + ATTACH devbase AT atlist veclist_opt devattach_opt attrs_opt + = { defdevattach($6, $2, $4, $5, + $7); } | MAXUSERS NUMBER NUMBER NUMBER = { setdefmaxusers($2, $3, $4); } | - PSEUDO_DEVICE devbase attrs_opt = { defdev($2,1,NULL,NULL,NULL,$3); } | + PSEUDO_DEVICE devbase attrs_opt = { defdev($2,1,NULL,$3); } | MAJOR '{' majorlist '}'; atlist: - atlist ',' atname = { ($$ = new_n($3))->nv_next = $1; } | + atlist ',' atname = { $$ = new_nx($3, $1); } | atname = { $$ = new_n($1); }; atname: @@ -214,14 +236,18 @@ veclist_opt: /* veclist order matters, must use right recursion */ veclist: - WORD veclist = { ($$ = new_n($1))->nv_next = $2; } | + WORD veclist = { $$ = new_nx($1, $2); } | WORD = { $$ = new_n($1); }; devbase: WORD = { $$ = getdevbase($1); }; +devattach_opt: + WITH WORD = { $$ = getdevattach($2); } | + /* empty */ = { $$ = NULL; }; + interface_opt: - '{' loclist_opt '}' = { ($$ = new_n(""))->nv_next = $2; } | + '{' loclist_opt '}' = { $$ = new_nx("", $2); } | /* empty */ = { $$ = NULL; }; loclist_opt: @@ -257,7 +283,7 @@ attrs_opt: /* empty */ = { $$ = NULL; }; attrs: - attrs ',' attr = { ($$ = new_p($3))->nv_next = $1; } | + attrs ',' attr = { $$ = new_px($3, $1); } | attr = { $$ = new_p($1); }; attr: @@ -351,7 +377,6 @@ device_instance: attachment: ROOT = { $$ = NULL; } | WORD '?' = { $$ = wildref($1); } | - WORD '*' = { $$ = starref($1); } | WORD = { $$ = $1; }; locators: diff --git a/usr.sbin/config/hash.c b/usr.sbin/config/hash.c index e1290fd9456..538b7a703ff 100644 --- a/usr.sbin/config/hash.c +++ b/usr.sbin/config/hash.c @@ -1,5 +1,5 @@ -/* $OpenBSD: hash.c,v 1.2 1996/03/25 15:55:05 niklas Exp $ */ -/* $NetBSD: hash.c,v 1.2 1996/03/03 17:28:15 thorpej Exp $ */ +/* $OpenBSD: hash.c,v 1.3 1996/04/21 23:40:12 deraadt Exp $ */ +/* $NetBSD: hash.c,v 1.3 1996/03/17 13:18:20 cgd Exp $ */ /* * Copyright (c) 1992, 1993 @@ -262,6 +262,8 @@ ht_insrep(ht, nam, val, replace) } *hpp = hp = newhashent(nam, h); hp->h_value = val; + if (++ht->ht_used > ht->ht_lim) + ht_expand(ht); return (0); } diff --git a/usr.sbin/config/main.c b/usr.sbin/config/main.c index 5a2539a6e5b..c0e4482d74a 100644 --- a/usr.sbin/config/main.c +++ b/usr.sbin/config/main.c @@ -1,7 +1,7 @@ -/* $OpenBSD: main.c,v 1.3 1996/03/25 15:55:06 niklas Exp $ */ -/* $NetBSD: main.c,v 1.13 1996/03/03 17:28:17 thorpej Exp $ */ +/* $OpenBSD: main.c,v 1.4 1996/04/21 23:40:14 deraadt Exp $ */ +/* $NetBSD: main.c,v 1.17 1996/03/17 11:50:13 cgd Exp $ */ -/* +/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -78,7 +78,6 @@ static int do_option __P((struct hashtab *, struct nvlist ***, static int crosscheck __P((void)); static int badstar __P((void)); static int mksymlinks __P((void)); -static int has_instances __P((struct devbase *, int)); static int hasparent __P((struct devi *)); static int cfcrosscheck __P((struct config *, const char *, struct nvlist *)); @@ -150,6 +149,7 @@ usage: initfiles(); initsem(); devbasetab = ht_new(); + devatab = ht_new(); selecttab = ht_new(); needcnttab = ht_new(); opttab = ht_new(); @@ -323,7 +323,7 @@ do_option(ht, nppp, name, value, type) register struct nvlist *nv; /* assume it will work */ - nv = newnv(name, value, NULL, 0); + nv = newnv(name, value, NULL, 0, NULL); if (ht_insert(ht, name, nv) == 0) { **nppp = nv; *nppp = &nv->nv_next; @@ -343,23 +343,40 @@ do_option(ht, nppp, name, value, type) /* * Return true if there is at least one instance of the given unit - * on the given base (or any units, if unit == WILD). + * on the given device attachment (or any units, if unit == WILD). */ -static int -has_instances(dev, unit) - register struct devbase *dev; +int +deva_has_instances(deva, unit) + register struct deva *deva; int unit; { register struct devi *i; if (unit == WILD) - return (dev->d_ihead != NULL); - for (i = dev->d_ihead; i != NULL; i = i->i_bsame) + return (deva->d_ihead != NULL); + for (i = deva->d_ihead; i != NULL; i = i->i_asame) if (unit == i->i_unit) return (1); return (0); } +/* + * Return true if there is at least one instance of the given unit + * on the given base (or any units, if unit == WILD). + */ +int +devbase_has_instances(dev, unit) + register struct devbase *dev; + int unit; +{ + register struct deva *da; + + for (da = dev->d_ahead; da != NULL; da = da->d_bsame) + if (deva_has_instances(da, unit)) + return (1); + return (0); +} + static int hasparent(i) register struct devi *i; @@ -367,11 +384,30 @@ hasparent(i) register struct nvlist *nv; int atunit = i->i_atunit; - if (i->i_atdev != NULL && has_instances(i->i_atdev, atunit)) - return (1); + /* + * We determine whether or not a device has a parent in in one + * of two ways: + * (1) If a parent device was named in the config file, + * i.e. cases (2) and (3) in sem.c:adddev(), then + * we search its devbase for a matching unit number. + * (2) If the device was attach to an attribute, then we + * search all attributes the device can be attached to + * for parents (with appropriate unit numebrs) that + * may be able to attach the device. + */ + + /* + * Case (1): A parent was named. Either it's configured, or not. + */ + if (i->i_atdev != NULL) + return (devbase_has_instances(i->i_atdev, atunit)); + + /* + * Case (2): No parent was named. Look for devs that provide the attr. + */ if (i->i_atattr != NULL) for (nv = i->i_atattr->a_refs; nv != NULL; nv = nv->nv_next) - if (has_instances(nv->nv_ptr, atunit)) + if (devbase_has_instances(nv->nv_ptr, atunit)) return (1); return (0); } @@ -384,7 +420,7 @@ cfcrosscheck(cf, what, nv) { register struct devbase *dev; register struct devi *pd; - int errs; + int errs, devminor; for (errs = 0; nv != NULL; nv = nv->nv_next) { if (nv->nv_name == NULL) @@ -392,13 +428,15 @@ cfcrosscheck(cf, what, nv) dev = ht_lookup(devbasetab, nv->nv_name); if (dev == NULL) panic("cfcrosscheck(%s)", nv->nv_name); - if (has_instances(dev, STAR) || - has_instances(dev, minor(nv->nv_int) / maxpartitions)) + devminor = minor(nv->nv_int) / maxpartitions; + if (devbase_has_instances(dev, devminor)) + continue; + if (devbase_has_instances(dev, STAR) && + devminor >= dev->d_umax) continue; for (pd = allpseudo; pd != NULL; pd = pd->i_next) - if (pd->i_base == dev && - (minor(nv->nv_int) / maxpartitions) < dev->d_umax && - (minor(nv->nv_int) / maxpartitions) >= 0) + if (pd->i_base == dev && devminor < dev->d_umax && + devminor >= 0) goto loop; (void)fprintf(stderr, "%s%d: %s says %s on %s, but there's no %s\n", @@ -429,11 +467,9 @@ crosscheck() continue; xerror(conffile, i->i_lineno, "%s at %s is orphaned", i->i_name, i->i_at); - if (i->i_atunit == WILD) - (void)fprintf(stderr, " (no %s declared)\n", - i->i_at); - else - (void)fprintf(stderr, " (no %s declared)\n", i->i_at); + (void)fprintf(stderr, " (%s %s declared)\n", + i->i_atunit == WILD ? "nothing matching" : "no", + i->i_at); errs++; } if (allcf == NULL) { @@ -452,21 +488,23 @@ crosscheck() } /* - * Check to see if there is more than one *'d unit for any device, - * or a *'d unit with a needs-count file. + * Check to see if there is a *'d unit with a needs-count file. */ int badstar() { register struct devbase *d; + register struct deva *da; register struct devi *i; register int errs, n; errs = 0; for (d = allbases; d != NULL; d = d->d_next) { - for (i = d->d_ihead; i != NULL; i = i->i_bsame) - if (i->i_unit == STAR) - goto foundstar; + for (da = d->d_ahead; da != NULL; da = da->d_bsame) + for (i = da->d_ihead; i != NULL; i = i->i_asame) { + if (i->i_unit == STAR) + goto foundstar; + } continue; foundstar: if (ht_lookup(needcnttab, d->d_name)) { @@ -481,12 +519,6 @@ badstar() n++; if (n < 1) panic("badstar() n<1"); - if (n == 1) - continue; - (void)fprintf(stderr, - "config: %d %s*'s in configuration; can only have 1\n", - n, d->d_name); - errs++; } return (errs); } diff --git a/usr.sbin/config/mkheaders.c b/usr.sbin/config/mkheaders.c index 91ddb8c28ac..d158c209a22 100644 --- a/usr.sbin/config/mkheaders.c +++ b/usr.sbin/config/mkheaders.c @@ -1,7 +1,7 @@ -/* $OpenBSD: mkheaders.c,v 1.2 1996/03/25 15:55:07 niklas Exp $ */ -/* $NetBSD: mkheaders.c,v 1.8 1996/03/03 17:28:20 thorpej Exp $ */ +/* $OpenBSD: mkheaders.c,v 1.3 1996/04/21 23:40:15 deraadt Exp $ */ +/* $NetBSD: mkheaders.c,v 1.10 1996/03/17 13:18:21 cgd Exp $ */ -/* +/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -69,7 +69,7 @@ mkheaders() if (fi->fi_flags & FI_HIDDEN) continue; if (fi->fi_flags & (FI_NEEDSCOUNT | FI_NEEDSFLAG) && - emitcnt(fi->fi_opt)) + emitcnt(fi->fi_optf)) return (1); } return (0); diff --git a/usr.sbin/config/mkioconf.c b/usr.sbin/config/mkioconf.c index 56c40015a2e..c9b418d6831 100644 --- a/usr.sbin/config/mkioconf.c +++ b/usr.sbin/config/mkioconf.c @@ -1,7 +1,7 @@ -/* $OpenBSD: mkioconf.c,v 1.2 1996/03/25 15:55:08 niklas Exp $ */ -/* $NetBSD: mkioconf.c,v 1.36 1996/03/03 17:28:23 thorpej Exp $ */ +/* $OpenBSD: mkioconf.c,v 1.3 1996/04/21 23:40:17 deraadt Exp $ */ +/* $NetBSD: mkioconf.c,v 1.38 1996/03/17 06:29:27 cgd Exp $ */ -/* +/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -161,16 +161,25 @@ emitexterns(fp) register FILE *fp; { register struct devbase *d; + register struct deva *da; NEWLINE; for (d = allbases; d != NULL; d = d->d_next) { - if (d->d_ihead == NULL) + if (!devbase_has_instances(d, WILD)) continue; - if (fprintf(fp, "extern struct cfdriver %scd;\n", + if (fprintf(fp, "extern struct cfdriver %s_cd;\n", d->d_name) < 0) return (1); } NEWLINE; + for (da = alldevas; da != NULL; da = da->d_next) { + if (!deva_has_instances(da, WILD)) + continue; + if (fprintf(fp, "extern struct cfattach %s_ca;\n", + da->d_name) < 0) + return (1); + } + NEWLINE; return (0); } @@ -216,7 +225,7 @@ emitcfdata(fp) { register struct devi **p, *i, **par; register int unit, v; - register const char *vs, *state, *basename; + register const char *vs, *state, *basename, *attachment; register struct nvlist *nv; register struct attr *a; char *loc; @@ -227,7 +236,7 @@ emitcfdata(fp) #define STAR FSTATE_STAR\n\ \n\ struct cfdata cfdata[] = {\n\ -\t/* driver unit state loc flags parents ivstubs */\n") < 0) + /* attachment driver unit state loc flags parents ivstubs */\n") < 0) return (1); for (p = packed; (i = *p) != NULL; p++) { /* the description */ @@ -251,6 +260,7 @@ struct cfdata cfdata[] = {\n\ /* then the actual defining line */ basename = i->i_base->d_name; + attachment = i->i_atdeva->d_name; if (i->i_unit == STAR) { unit = i->i_base->d_umax; state = "STAR"; @@ -271,12 +281,13 @@ struct cfdata cfdata[] = {\n\ } else loc = "loc"; if (fprintf(fp, "\ -\t{&%scd,%s%2d, %s, %7s, %#6x, pv+%2d, %s%d},\n", + {&%s_ca,%s&%s_cd,%s%2d, %s, %7s, %#6x, pv+%2d, %s%d},\n", + attachment, strlen(attachment) < 6 ? "\t\t" : "\t", basename, strlen(basename) < 3 ? "\t\t" : "\t", unit, state, loc, i->i_cfflags, i->i_pvoff, vs, v) < 0) return (1); } - return (fputs("\t{0}\n};\n", fp) < 0); + return (fputs(" {0}\n};\n", fp) < 0); } /* @@ -346,7 +357,7 @@ emitvec(fp) nvec = 0; for (p = packed; (i = *p) != NULL; p++) { - if ((head = i->i_base->d_vectors) == NULL) + if ((head = i->i_atdeva->d_vectors) == NULL) continue; if ((unit = i->i_unit) == STAR) panic("emitvec unit==STAR"); @@ -366,7 +377,7 @@ emitvec(fp) return (1); nvec = 0; for (p = packed; (i = *p) != NULL; p++) { - if ((head = i->i_base->d_vectors) == NULL) + if ((head = i->i_atdeva->d_vectors) == NULL) continue; i->i_ivoff = nvec; unit = i->i_unit; diff --git a/usr.sbin/config/mkmakefile.c b/usr.sbin/config/mkmakefile.c index 237ea6c1a17..33a31571ace 100644 --- a/usr.sbin/config/mkmakefile.c +++ b/usr.sbin/config/mkmakefile.c @@ -1,7 +1,7 @@ -/* $OpenBSD: mkmakefile.c,v 1.2 1996/03/25 15:55:09 niklas Exp $ */ -/* $NetBSD: mkmakefile.c,v 1.27 1996/03/03 17:28:26 thorpej Exp $ */ +/* $OpenBSD: mkmakefile.c,v 1.3 1996/04/21 23:40:18 deraadt Exp $ */ +/* $NetBSD: mkmakefile.c,v 1.29 1996/03/17 13:18:23 cgd Exp $ */ -/* +/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -53,15 +53,19 @@ #include <string.h> #include "config.h" #include "sem.h" + /* * Make the Makefile. */ +static const char *srcpath __P((struct files *)); + static int emitdefs __P((FILE *)); +static int emitfiles __P((FILE *, int)); + static int emitobjs __P((FILE *)); static int emitcfiles __P((FILE *)); static int emitsfiles __P((FILE *)); -static int emitfiles __P((FILE *, int)); static int emitrules __P((FILE *)); static int emitload __P((FILE *)); @@ -142,6 +146,33 @@ bad: return (1); } +/* + * Return (possibly in a static buffer) the name of the `source' for a + * file. If we have `options source', or if the file is marked `always + * source', this is always the path from the `file' line; otherwise we + * get the .o from the obj-directory. + */ +static const char * +srcpath(fi) + register struct files *fi; +{ +#if 1 + /* Always have source, don't support object dirs for kernel builds. */ + return (fi->fi_path); +#else + static char buf[MAXPATHLEN]; + + if (have_source || (fi->fi_flags & FI_ALWAYSSRC) != 0) + return (fi->fi_path); + if (objpath == NULL) { + error("obj-directory not set"); + return (NULL); + } + (void)snprintf(buf, sizeof buf, "%s/%s.o", objpath, fi->fi_base); + return (buf); +#endif +} + static int emitdefs(fp) register FILE *fp; @@ -225,6 +256,7 @@ emitfiles(fp, suffix) register struct files *fi; register struct config *cf; register int lpos, len, sp; + register const char *fpath; char swapname[100]; if (fprintf(fp, "%cFILES=", toupper(suffix)) < 0) @@ -234,10 +266,12 @@ emitfiles(fp, suffix) for (fi = allfiles; fi != NULL; fi = fi->fi_next) { if ((fi->fi_flags & FI_SEL) == 0) continue; - len = strlen(fi->fi_path); - if (fi->fi_path[len - 1] != suffix) + if ((fpath = srcpath(fi)) == NULL) + return (1); + len = strlen(fpath); + if (fpath[len - 1] != suffix) continue; - if (*fi->fi_path != '/') + if (*fpath != '/') len += 3; /* "$S/" */ if (lpos + len > 72) { if (fputs(" \\\n", fp) < 0) @@ -245,8 +279,8 @@ emitfiles(fp, suffix) sp = '\t'; lpos = 7; } - if (fprintf(fp, "%c%s%s", sp, *fi->fi_path != '/' ? "$S/" : "", - fi->fi_path) < 0) + if (fprintf(fp, "%c%s%s", sp, *fpath != '/' ? "$S/" : "", + fpath) < 0) return (1); lpos += len + 1; sp = ' '; @@ -291,19 +325,21 @@ emitrules(fp) register FILE *fp; { register struct files *fi; - register const char *cp; + register const char *cp, *fpath; int ch; char buf[200]; for (fi = allfiles; fi != NULL; fi = fi->fi_next) { if ((fi->fi_flags & FI_SEL) == 0) continue; + if ((fpath = srcpath(fi)) == NULL) + return (1); if (fprintf(fp, "%s.o: %s%s\n", fi->fi_base, - *fi->fi_path != '/' ? "$S/" : "", fi->fi_path) < 0) + *fpath != '/' ? "$S/" : "", fpath) < 0) return (1); if ((cp = fi->fi_mkrule) == NULL) { cp = fi->fi_flags & FI_DRIVER ? "DRIVER" : "NORMAL"; - ch = fi->fi_lastc; + ch = fpath[strlen(fpath) - 1]; if (islower(ch)) ch = toupper(ch); (void)sprintf(buf, "${%s_%c%s}", cp, ch, diff --git a/usr.sbin/config/mkswap.c b/usr.sbin/config/mkswap.c index 83e86bb106c..53171687799 100644 --- a/usr.sbin/config/mkswap.c +++ b/usr.sbin/config/mkswap.c @@ -1,7 +1,7 @@ -/* $OpenBSD: mkswap.c,v 1.2 1996/03/25 15:55:10 niklas Exp $ */ -/* $NetBSD: mkswap.c,v 1.2 1996/03/03 17:28:29 thorpej Exp $ */ +/* $OpenBSD: mkswap.c,v 1.3 1996/04/21 23:40:20 deraadt Exp $ */ +/* $NetBSD: mkswap.c,v 1.4 1996/03/17 20:36:25 christos Exp $ */ -/* +/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -121,9 +121,9 @@ mkoneswap(cf) goto wrerror; mountroot = cf->cf_root->nv_str == s_nfs ? "nfs_mountroot" : "ffs_mountroot"; - if (fprintf(fp, "extern int %s();\n", mountroot) < 0) + if (fprintf(fp, "extern int %s __P((void *));\n", mountroot) < 0) goto wrerror; - if (fprintf(fp, "int (*mountroot)() = %s;\n", mountroot) < 0) + if (fprintf(fp, "int (*mountroot) __P((void *)) = %s;\n", mountroot) < 0) goto wrerror; if (fclose(fp)) { diff --git a/usr.sbin/config/pack.c b/usr.sbin/config/pack.c index 9e0b6330004..c3378c0c8b1 100644 --- a/usr.sbin/config/pack.c +++ b/usr.sbin/config/pack.c @@ -1,7 +1,7 @@ -/* $OpenBSD: pack.c,v 1.2 1996/03/25 15:55:11 niklas Exp $ */ -/* $NetBSD: pack.c,v 1.2 1996/03/03 17:28:32 thorpej Exp $ */ +/* $OpenBSD: pack.c,v 1.3 1996/04/21 23:40:21 deraadt Exp $ */ +/* $NetBSD: pack.c,v 1.3 1996/03/17 06:29:33 cgd Exp $ */ -/* +/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * diff --git a/usr.sbin/config/scan.l b/usr.sbin/config/scan.l index 9f211c640b1..d79648c34d7 100644 --- a/usr.sbin/config/scan.l +++ b/usr.sbin/config/scan.l @@ -1,8 +1,8 @@ %{ -/* $OpenBSD: scan.l,v 1.2 1996/03/25 15:55:12 niklas Exp $ */ -/* $NetBSD: scan.l,v 1.2 1996/03/03 17:28:34 thorpej Exp $ */ +/* $OpenBSD: scan.l,v 1.3 1996/04/21 23:40:23 deraadt Exp $ */ +/* $NetBSD: scan.l,v 1.4 1996/03/17 06:29:35 cgd Exp $ */ -/* +/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -87,6 +87,7 @@ WORD [A-Za-z_][-A-Za-z_0-9]* /* plain keywords */ and { return AND; } at { return AT; } +attach { return ATTACH; } compile-with { return COMPILE_WITH; } config { return CONFIG; } define { return DEFINE; } @@ -107,6 +108,7 @@ options { return OPTIONS; } root { return ROOT; } swap { return SWAP; } vector { return VECTOR; } +with { return WITH; } /* keywords with values */ config-dependent { yylval.val = FI_CONFIGDEP; return FFLAG; } 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); + } + } } /* diff --git a/usr.sbin/config/sem.h b/usr.sbin/config/sem.h index 131762f7a47..ede56255b01 100644 --- a/usr.sbin/config/sem.h +++ b/usr.sbin/config/sem.h @@ -1,7 +1,7 @@ -/* $OpenBSD: sem.h,v 1.2 1996/03/25 15:55:14 niklas Exp $ */ -/* $NetBSD: sem.h,v 1.2 1996/03/03 17:28:39 thorpej Exp $ */ +/* $OpenBSD: sem.h,v 1.3 1996/04/21 23:40:27 deraadt Exp $ */ +/* $NetBSD: sem.h,v 1.4 1996/03/17 06:29:40 cgd Exp $ */ -/* +/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -51,8 +51,11 @@ void setdefmaxusers __P((int, int, int)); void setmaxusers __P((int)); int defattr __P((const char *, struct nvlist *)); void defdev __P((struct devbase *, int, struct nvlist *, + struct nvlist *)); +void defdevattach __P((struct deva *, struct devbase *, struct nvlist *, struct nvlist *, struct nvlist *)); struct devbase *getdevbase __P((const char *name)); +struct deva *getdevattach __P((const char *name)); struct attr *getattr __P((const char *name)); void setmajor __P((struct devbase *d, int n)); void addconf __P((struct config *)); diff --git a/usr.sbin/config/util.c b/usr.sbin/config/util.c index ca6b2eddb22..c9db10cda80 100644 --- a/usr.sbin/config/util.c +++ b/usr.sbin/config/util.c @@ -1,7 +1,7 @@ -/* $OpenBSD: util.c,v 1.2 1996/03/25 15:55:16 niklas Exp $ */ -/* $NetBSD: util.c,v 1.2 1996/03/03 17:28:41 thorpej Exp $ */ +/* $OpenBSD: util.c,v 1.3 1996/04/21 23:40:28 deraadt Exp $ */ +/* $NetBSD: util.c,v 1.4 1996/03/17 11:50:16 cgd Exp $ */ -/* +/* * Copyright (c) 1992, 1993 * The Regents of the University of California. All rights reserved. * @@ -60,7 +60,7 @@ static void nomem __P((void)); static void vxerror __P((const char *, int, const char *, va_list)); -/* +/* * Malloc, with abort on error. */ void * @@ -74,7 +74,7 @@ emalloc(size) return (p); } -/* +/* * Realloc, with abort on error. */ void * @@ -120,10 +120,11 @@ path(file) static struct nvlist *nvhead; struct nvlist * -newnv(name, str, ptr, i) +newnv(name, str, ptr, i, next) const char *name, *str; void *ptr; int i; + struct nvlist *next; { register struct nvlist *nv; @@ -131,7 +132,7 @@ newnv(name, str, ptr, i) nv = emalloc(sizeof(*nv)); else nvhead = nv->nv_next; - nv->nv_next = NULL; + nv->nv_next = next; nv->nv_name = name; if (ptr == NULL) nv->nv_str = str; |