1 /* $NetBSD: sem.c,v 1.83 2018/04/09 17:46:56 christos Exp $ */ 2 3 /* 4 * Copyright (c) 1992, 1993 5 * The Regents of the University of California. All rights reserved. 6 * 7 * This software was developed by the Computer Systems Engineering group 8 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 9 * contributed to Berkeley. 10 * 11 * All advertising materials mentioning features or use of this software 12 * must display the following acknowledgement: 13 * This product includes software developed by the University of 14 * California, Lawrence Berkeley Laboratories. 15 * 16 * Redistribution and use in source and binary forms, with or without 17 * modification, are permitted provided that the following conditions 18 * are met: 19 * 1. Redistributions of source code must retain the above copyright 20 * notice, this list of conditions and the following disclaimer. 21 * 2. Redistributions in binary form must reproduce the above copyright 22 * notice, this list of conditions and the following disclaimer in the 23 * documentation and/or other materials provided with the distribution. 24 * 3. Neither the name of the University nor the names of its contributors 25 * may be used to endorse or promote products derived from this software 26 * without specific prior written permission. 27 * 28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 38 * SUCH DAMAGE. 39 * 40 * from: @(#)sem.c 8.1 (Berkeley) 6/6/93 41 */ 42 43 #if HAVE_NBTOOL_CONFIG_H 44 #include "nbtool_config.h" 45 #endif 46 47 #include <sys/cdefs.h> 48 __RCSID("$NetBSD: sem.c,v 1.83 2018/04/09 17:46:56 christos Exp $"); 49 50 #include <sys/param.h> 51 #include <ctype.h> 52 #include <stdio.h> 53 #include <stdlib.h> 54 #include <string.h> 55 #include <util.h> 56 #include "defs.h" 57 #include "sem.h" 58 59 /* 60 * config semantics. 61 */ 62 63 #define NAMESIZE 100 /* local name buffers */ 64 65 const char *s_ifnet; /* magic attribute */ 66 const char *s_qmark; 67 const char *s_none; 68 69 static struct hashtab *cfhashtab; /* for config lookup */ 70 struct hashtab *devitab; /* etc */ 71 struct attr allattr; 72 size_t nattrs; 73 74 static struct attr errattr; 75 static struct devbase errdev; 76 static struct deva errdeva; 77 78 static int has_errobj(struct attrlist *, struct attr *); 79 static struct nvlist *addtoattr(struct nvlist *, struct devbase *); 80 static int resolve(struct nvlist **, const char *, const char *, 81 struct nvlist *, int); 82 static struct pspec *getpspec(struct attr *, struct devbase *, int, int); 83 static struct devi *newdevi(const char *, int, struct devbase *d); 84 static struct devi *getdevi(const char *); 85 static void remove_devi(struct devi *); 86 static const char *concat(const char *, int); 87 static char *extend(char *, const char *); 88 static int split(const char *, size_t, char *, size_t, int *); 89 static void selectbase(struct devbase *, struct deva *); 90 static const char **fixloc(const char *, struct attr *, struct loclist *); 91 static const char *makedevstr(devmajor_t, devminor_t); 92 static const char *major2name(devmajor_t); 93 static devmajor_t dev2major(struct devbase *); 94 95 extern const char *yyfile; 96 extern int vflag; 97 98 #define V_ATTRIBUTE 0 99 #define V_DEVICE 1 100 struct vtype { 101 int type; 102 struct attr *attr; 103 void *value; 104 }; 105 106 static struct nvlist * 107 makedevstack(struct devbase *d) 108 { 109 struct devi *firsti, *i; 110 struct nvlist *stack = NULL; 111 112 for (firsti = d->d_ihead; firsti != NULL; firsti = firsti->i_bsame) 113 for (i = firsti; i != NULL; i = i->i_alias) 114 stack = newnv(NULL, NULL, i, 0, stack); 115 return stack; 116 } 117 118 static void 119 devcleanup(struct nvlist *stack) 120 { 121 struct nvlist *nv; 122 for (nv = stack; nv != NULL; nv = nv->nv_next) 123 remove_devi(nv->nv_ptr); 124 nvfreel(stack); 125 } 126 127 static void * 128 addvalue(int type, struct attr *a, void *value) 129 { 130 struct vtype *vt = emalloc(sizeof(*vt)); 131 vt->type = type; 132 vt->attr = a; 133 vt->value = value; 134 return vt; 135 } 136 137 void 138 initsem(void) 139 { 140 141 attrtab = ht_new(); 142 attrdeptab = ht_new(); 143 144 allattr.a_name = "netbsd"; 145 TAILQ_INIT(&allattr.a_files); 146 (void)ht_insert(attrtab, allattr.a_name, &allattr); 147 selectattr(&allattr); 148 149 errattr.a_name = "<internal>"; 150 151 TAILQ_INIT(&allbases); 152 153 TAILQ_INIT(&alldevas); 154 155 TAILQ_INIT(&allpspecs); 156 157 cfhashtab = ht_new(); 158 TAILQ_INIT(&allcf); 159 160 TAILQ_INIT(&alldevi); 161 errdev.d_name = "<internal>"; 162 163 TAILQ_INIT(&allpseudo); 164 165 TAILQ_INIT(&alldevms); 166 167 s_ifnet = intern("ifnet"); 168 s_qmark = intern("?"); 169 s_none = intern("none"); 170 } 171 172 /* Name of include file just ended (set in scan.l) */ 173 extern const char *lastfile; 174 175 static struct attr * 176 finddep(struct attr *a, const char *name) 177 { 178 struct attrlist *al; 179 180 for (al = a->a_deps; al != NULL; al = al->al_next) { 181 struct attr *this = al->al_this; 182 if (strcmp(this->a_name, name) == 0) 183 return this; 184 } 185 return NULL; 186 } 187 188 static void 189 mergedeps(const char *dname, const char *name) 190 { 191 struct attr *a, *newa; 192 193 CFGDBG(4, "merging attr `%s' to devbase `%s'", name, dname); 194 a = refattr(dname); 195 if (finddep(a, name) == NULL) { 196 newa = refattr(name); 197 a->a_deps = attrlist_cons(a->a_deps, newa); 198 CFGDBG(3, "attr `%s' merged to attr `%s'", newa->a_name, 199 a->a_name); 200 } 201 } 202 203 static void 204 fixdev(struct devbase *dev) 205 { 206 struct attrlist *al; 207 struct attr *devattr, *a; 208 209 devattr = refattr(dev->d_name); 210 if (devattr->a_devclass) 211 panic("%s: dev %s is devclass!", __func__, devattr->a_name); 212 213 CFGDBG(4, "fixing devbase `%s'", dev->d_name); 214 for (al = dev->d_attrs; al != NULL; al = al->al_next) { 215 a = al->al_this; 216 CFGDBG(4, "fixing devbase `%s' attr `%s'", dev->d_name, 217 a->a_name); 218 if (a->a_iattr) { 219 a->a_refs = addtoattr(a->a_refs, dev); 220 CFGDBG(3, "device `%s' has iattr `%s'", dev->d_name, 221 a->a_name); 222 } else if (a->a_devclass != NULL) { 223 if (dev->d_classattr != NULL && dev->d_classattr != a) { 224 cfgwarn("device `%s' has multiple classes " 225 "(`%s' and `%s')", 226 dev->d_name, dev->d_classattr->a_name, 227 a->a_name); 228 } 229 if (dev->d_classattr == NULL) { 230 dev->d_classattr = a; 231 CFGDBG(3, "device `%s' is devclass `%s'", 232 dev->d_name, a->a_name); 233 } 234 } else { 235 if (strcmp(dev->d_name, a->a_name) != 0) { 236 mergedeps(dev->d_name, a->a_name); 237 } 238 } 239 } 240 } 241 242 void 243 enddefs(void) 244 { 245 struct devbase *dev; 246 247 yyfile = "enddefs"; 248 249 TAILQ_FOREACH(dev, &allbases, d_next) { 250 if (!dev->d_isdef) { 251 (void)fprintf(stderr, 252 "%s: device `%s' used but not defined\n", 253 lastfile, dev->d_name); 254 errors++; 255 continue; 256 } 257 fixdev(dev); 258 } 259 if (errors) { 260 (void)fprintf(stderr, "*** Stop.\n"); 261 exit(1); 262 } 263 } 264 265 void 266 setdefmaxusers(int min, int def, int max) 267 { 268 269 if (min < 1 || min > def || def > max) 270 cfgerror("maxusers must have 1 <= min (%d) <= default (%d) " 271 "<= max (%d)", min, def, max); 272 else { 273 minmaxusers = min; 274 defmaxusers = def; 275 maxmaxusers = max; 276 } 277 } 278 279 void 280 setmaxusers(int n) 281 { 282 283 if (maxusers == n) { 284 cfgerror("duplicate maxusers parameter"); 285 return; 286 } 287 if (vflag && maxusers != 0) 288 cfgwarn("warning: maxusers already defined"); 289 maxusers = n; 290 if (n < minmaxusers) { 291 cfgerror("warning: minimum of %d maxusers assumed", 292 minmaxusers); 293 errors--; /* take it away */ 294 maxusers = minmaxusers; 295 } else if (n > maxmaxusers) { 296 cfgerror("warning: maxusers (%d) > %d", n, maxmaxusers); 297 errors--; 298 } 299 } 300 301 void 302 setident(const char *i) 303 { 304 305 if (i) 306 ident = intern(i); 307 else 308 ident = NULL; 309 } 310 311 /* 312 * Define an attribute, optionally with an interface (a locator list) 313 * and a set of attribute-dependencies. 314 * 315 * Attribute dependencies MAY NOT be interface attributes. 316 * 317 * Since an empty locator list is logically different from "no interface", 318 * all locator lists include a dummy head node, which we discard here. 319 */ 320 int 321 defattr0(const char *name, struct loclist *locs, struct attrlist *deps, 322 int devclass) 323 { 324 325 if (locs != NULL) 326 return defiattr(name, locs, deps, devclass); 327 else if (devclass) 328 return defdevclass(name, locs, deps, devclass); 329 else 330 return defattr(name, locs, deps, devclass); 331 } 332 333 int 334 defattr(const char *name, struct loclist *locs, struct attrlist *deps, 335 int devclass) 336 { 337 struct attr *a, *dep; 338 struct attrlist *al; 339 340 if (getrefattr(name, &a)) { 341 cfgerror("attribute `%s' already defined", name); 342 loclist_destroy(locs); 343 return (1); 344 } 345 if (a == NULL) 346 a = mkattr(name); 347 348 /* 349 * If this attribute depends on any others, make sure none of 350 * the dependencies are interface attributes. 351 */ 352 for (al = deps; al != NULL; al = al->al_next) { 353 dep = al->al_this; 354 if (dep->a_iattr) { 355 cfgerror("`%s' dependency `%s' is an interface " 356 "attribute", name, dep->a_name); 357 return (1); 358 } 359 (void)ht_insert2(attrdeptab, name, dep->a_name, 360 addvalue(V_ATTRIBUTE, a, dep)); 361 CFGDBG(2, "attr `%s' depends on attr `%s'", name, dep->a_name); 362 } 363 364 365 a->a_deps = deps; 366 expandattr(a, NULL); 367 CFGDBG(3, "attr `%s' defined", a->a_name); 368 369 return (0); 370 } 371 372 struct attr * 373 mkattr(const char *name) 374 { 375 struct attr *a; 376 377 a = ecalloc(1, sizeof *a); 378 if (ht_insert(attrtab, name, a)) { 379 free(a); 380 return NULL; 381 } 382 a->a_name = name; 383 TAILQ_INIT(&a->a_files); 384 CFGDBG(3, "attr `%s' allocated", name); 385 386 return a; 387 } 388 389 /* "interface attribute" initialization */ 390 int 391 defiattr(const char *name, struct loclist *locs, struct attrlist *deps, 392 int devclass) 393 { 394 struct attr *a; 395 int len; 396 struct loclist *ll; 397 398 if (devclass) 399 panic("%s: %s has both locators and devclass", __func__, name); 400 401 if (defattr(name, locs, deps, devclass) != 0) 402 return (1); 403 404 a = getattr(name); 405 a->a_iattr = 1; 406 /* unwrap */ 407 a->a_locs = locs->ll_next; 408 locs->ll_next = NULL; 409 loclist_destroy(locs); 410 len = 0; 411 for (ll = a->a_locs; ll != NULL; ll = ll->ll_next) 412 len++; 413 a->a_loclen = len; 414 if (deps) 415 CFGDBG(2, "attr `%s' iface with deps", a->a_name); 416 return (0); 417 } 418 419 /* "device class" initialization */ 420 int 421 defdevclass(const char *name, struct loclist *locs, struct attrlist *deps, 422 int devclass) 423 { 424 struct attr *a; 425 char classenum[256], *cp; 426 int errored = 0; 427 428 if (deps) 429 panic("%s: %s has both dependencies and devclass", __func__, 430 name); 431 432 if (defattr(name, locs, deps, devclass) != 0) 433 return (1); 434 435 a = getattr(name); 436 (void)snprintf(classenum, sizeof(classenum), "DV_%s", name); 437 for (cp = classenum + 3; *cp; cp++) { 438 if (!errored && (!isalnum((unsigned char)*cp) || 439 (isalpha((unsigned char)*cp) 440 && !islower((unsigned char)*cp)))) { 441 cfgerror("device class names must be " 442 "lower-case alphanumeric characters"); 443 errored = 1; 444 } 445 *cp = (char)toupper((unsigned char)*cp); 446 } 447 a->a_devclass = intern(classenum); 448 449 return (0); 450 } 451 452 /* 453 * Return true if the given `error object' is embedded in the given 454 * pointer list. 455 */ 456 static int 457 has_errobj(struct attrlist *al, struct attr *obj) 458 { 459 460 for (; al != NULL; al = al->al_next) 461 if (al->al_this == obj) 462 return (1); 463 return (0); 464 } 465 466 /* 467 * Return true if the given attribute is embedded in the given 468 * pointer list. 469 */ 470 int 471 has_attr(struct attrlist *al, const char *attr) 472 { 473 struct attr *a; 474 475 if ((a = getattr(attr)) == NULL) 476 return (0); 477 478 for (; al != NULL; al = al->al_next) 479 if (al->al_this == a) 480 return (1); 481 return (0); 482 } 483 484 /* 485 * Add a device base to a list in an attribute (actually, to any list). 486 * Note that this does not check for duplicates, and does reverse the 487 * list order, but no one cares anyway. 488 */ 489 static struct nvlist * 490 addtoattr(struct nvlist *l, struct devbase *dev) 491 { 492 struct nvlist *n; 493 494 n = newnv(NULL, NULL, dev, 0, l); 495 return (n); 496 } 497 498 /* 499 * Define a device. This may (or may not) also define an interface 500 * attribute and/or refer to existing attributes. 501 */ 502 void 503 defdev(struct devbase *dev, struct loclist *loclist, struct attrlist *attrs, 504 int ispseudo) 505 { 506 struct loclist *ll; 507 struct attrlist *al; 508 509 if (dev == &errdev) 510 goto bad; 511 if (dev->d_isdef) { 512 cfgerror("redefinition of `%s' (previously defined at %s:%d)", 513 dev->d_name, dev->d_srcfile, dev->d_srcline); 514 goto bad; 515 } 516 517 dev->d_isdef = 1; 518 if (has_errobj(attrs, &errattr)) 519 goto bad; 520 521 /* 522 * Handle implicit attribute definition from locator list. Do 523 * this before scanning the `at' list so that we can have, e.g.: 524 * device foo at other, foo { slot = -1 } 525 * (where you can plug in a foo-bus extender to a foo-bus). 526 */ 527 if (loclist != NULL) { 528 ll = loclist; 529 loclist = NULL; /* defattr disposes of them for us */ 530 if (defiattr(dev->d_name, ll, NULL, 0)) 531 goto bad; 532 attrs = attrlist_cons(attrs, getattr(dev->d_name)); 533 /* This used to be stored but was never used */ 534 /* attrs->al_name = dev->d_name; */ 535 } 536 537 /* 538 * Pseudo-devices can have children. Consider them as 539 * attaching at root. 540 */ 541 if (ispseudo) { 542 for (al = attrs; al != NULL; al = al->al_next) 543 if (al->al_this->a_iattr) 544 break; 545 if (al != NULL) { 546 if (ispseudo < 2) { 547 if (version >= 20080610) 548 cfgerror("interface attribute on " 549 "non-device pseudo `%s'", dev->d_name); 550 else { 551 ispseudo = 2; 552 } 553 } 554 ht_insert(devroottab, dev->d_name, dev); 555 } 556 } 557 558 /* Committed! Set up fields. */ 559 dev->d_ispseudo = ispseudo; 560 dev->d_attrs = attrs; 561 dev->d_classattr = NULL; /* for now */ 562 CFGDBG(3, "dev `%s' defined", dev->d_name); 563 564 /* 565 * Implicit attribute definition for device. 566 */ 567 refattr(dev->d_name); 568 569 /* 570 * For each interface attribute this device refers to, add this 571 * device to its reference list. This makes, e.g., finding all 572 * "scsi"s easier. 573 * 574 * While looking through the attributes, set up the device 575 * class if any are devclass attributes (and error out if the 576 * device has two classes). 577 */ 578 for (al = attrs; al != NULL; al = al->al_next) { 579 /* 580 * Implicit attribute definition for device dependencies. 581 */ 582 refattr(al->al_this->a_name); 583 (void)ht_insert2(attrdeptab, dev->d_name, al->al_this->a_name, 584 addvalue(V_DEVICE, al->al_this, dev)); 585 CFGDBG(2, "device `%s' depends on attr `%s'", dev->d_name, 586 al->al_this->a_name); 587 } 588 return; 589 bad: 590 loclist_destroy(loclist); 591 attrlist_destroyall(attrs); 592 } 593 594 /* 595 * Look up a devbase. Also makes sure it is a reasonable name, 596 * i.e., does not end in a digit or contain special characters. 597 */ 598 struct devbase * 599 getdevbase(const char *name) 600 { 601 const u_char *p; 602 struct devbase *dev; 603 604 p = (const u_char *)name; 605 if (!isalpha(*p)) 606 goto badname; 607 while (*++p) { 608 if (!isalnum(*p) && *p != '_') 609 goto badname; 610 } 611 if (isdigit(*--p)) { 612 badname: 613 cfgerror("bad device base name `%s'", name); 614 return (&errdev); 615 } 616 dev = ht_lookup(devbasetab, name); 617 if (dev == NULL) { 618 dev = ecalloc(1, sizeof *dev); 619 dev->d_name = name; 620 dev->d_isdef = 0; 621 dev->d_major = NODEVMAJOR; 622 dev->d_attrs = NULL; 623 dev->d_ihead = NULL; 624 dev->d_ipp = &dev->d_ihead; 625 dev->d_ahead = NULL; 626 dev->d_app = &dev->d_ahead; 627 dev->d_umax = 0; 628 dev->d_srcfile = yyfile; 629 dev->d_srcline = currentline(); 630 TAILQ_INSERT_TAIL(&allbases, dev, d_next); 631 if (ht_insert(devbasetab, name, dev)) 632 panic("%s: Can't insert %s", __func__, name); 633 CFGDBG(3, "devbase defined `%s'", dev->d_name); 634 } 635 return (dev); 636 } 637 638 /* 639 * Define some of a device's allowable parent attachments. 640 * There may be a list of (plain) attributes. 641 */ 642 void 643 defdevattach(struct deva *deva, struct devbase *dev, struct nvlist *atlist, 644 struct attrlist *attrs) 645 { 646 struct nvlist *nv; 647 struct attrlist *al; 648 struct attr *a; 649 650 if (dev == &errdev) 651 goto bad; 652 if (deva == NULL) 653 deva = getdevattach(dev->d_name); 654 if (deva == &errdeva) 655 goto bad; 656 if (!dev->d_isdef) { 657 cfgerror("attaching undefined device `%s'", dev->d_name); 658 goto bad; 659 } 660 if (deva->d_isdef) { 661 cfgerror("redefinition of `%s' (previously defined at %s:%d)", 662 deva->d_name, deva->d_srcfile, deva->d_srcline); 663 goto bad; 664 } 665 if (dev->d_ispseudo) { 666 cfgerror("pseudo-devices can't attach"); 667 goto bad; 668 } 669 670 deva->d_isdef = 1; 671 if (has_errobj(attrs, &errattr)) 672 goto bad; 673 for (al = attrs; al != NULL; al = al->al_next) { 674 a = al->al_this; 675 if (a == &errattr) 676 continue; /* already complained */ 677 if (a->a_iattr || a->a_devclass != NULL) 678 cfgerror("`%s' is not a plain attribute", a->a_name); 679 } 680 681 /* Committed! Set up fields. */ 682 deva->d_attrs = attrs; 683 deva->d_atlist = atlist; 684 deva->d_devbase = dev; 685 CFGDBG(3, "deva `%s' defined", deva->d_name); 686 687 /* 688 * Implicit attribute definition for device attachment. 689 */ 690 refattr(deva->d_name); 691 692 /* 693 * Turn the `at' list into interface attributes (map each 694 * nv_name to an attribute, or to NULL for root), and add 695 * this device to those attributes, so that children can 696 * be listed at this particular device if they are supported 697 * by that attribute. 698 */ 699 for (nv = atlist; nv != NULL; nv = nv->nv_next) { 700 if (nv->nv_name == NULL) 701 nv->nv_ptr = a = NULL; /* at root */ 702 else 703 nv->nv_ptr = a = getattr(nv->nv_name); 704 if (a == &errattr) 705 continue; /* already complained */ 706 707 #if 0 708 /* 709 * Make sure that an attachment spec doesn't 710 * already say how to attach to this attribute. 711 */ 712 for (struct deva *da = dev->d_ahead; da; da = da->d_bsame) 713 if (onlist(da->d_atlist, a)) 714 cfgerror("attach at `%s' already done by `%s'", 715 a ? a->a_name : "root", da->d_name); 716 #endif 717 718 if (a == NULL) { 719 ht_insert(devroottab, dev->d_name, dev); 720 continue; /* at root; don't add */ 721 } 722 if (!a->a_iattr) 723 cfgerror("%s cannot be at plain attribute `%s'", 724 dev->d_name, a->a_name); 725 else 726 a->a_devs = addtoattr(a->a_devs, dev); 727 } 728 729 /* attach to parent */ 730 *dev->d_app = deva; 731 dev->d_app = &deva->d_bsame; 732 return; 733 bad: 734 nvfreel(atlist); 735 attrlist_destroyall(attrs); 736 } 737 738 /* 739 * Look up a device attachment. Also makes sure it is a reasonable 740 * name, i.e., does not contain digits or special characters. 741 */ 742 struct deva * 743 getdevattach(const char *name) 744 { 745 const u_char *p; 746 struct deva *deva; 747 748 p = (const u_char *)name; 749 if (!isalpha(*p)) 750 goto badname; 751 while (*++p) { 752 if (!isalnum(*p) && *p != '_') 753 goto badname; 754 } 755 if (isdigit(*--p)) { 756 badname: 757 cfgerror("bad device attachment name `%s'", name); 758 return (&errdeva); 759 } 760 deva = ht_lookup(devatab, name); 761 if (deva == NULL) { 762 deva = ecalloc(1, sizeof *deva); 763 deva->d_name = name; 764 deva->d_bsame = NULL; 765 deva->d_isdef = 0; 766 deva->d_devbase = NULL; 767 deva->d_atlist = NULL; 768 deva->d_attrs = NULL; 769 deva->d_ihead = NULL; 770 deva->d_ipp = &deva->d_ihead; 771 deva->d_srcfile = yyfile; 772 deva->d_srcline = currentline(); 773 TAILQ_INSERT_TAIL(&alldevas, deva, d_next); 774 if (ht_insert(devatab, name, deva)) 775 panic("%s: Can't insert %s", __func__, name); 776 } 777 return (deva); 778 } 779 780 /* 781 * Look up an attribute. 782 */ 783 struct attr * 784 getattr(const char *name) 785 { 786 struct attr *a; 787 788 if ((a = ht_lookup(attrtab, name)) == NULL) { 789 cfgerror("undefined attribute `%s'", name); 790 a = &errattr; 791 } 792 return (a); 793 } 794 795 /* 796 * Implicit attribute definition. 797 */ 798 struct attr * 799 refattr(const char *name) 800 { 801 struct attr *a; 802 803 if ((a = ht_lookup(attrtab, name)) == NULL) 804 a = mkattr(name); 805 return a; 806 } 807 808 int 809 getrefattr(const char *name, struct attr **ra) 810 { 811 struct attr *a; 812 813 a = ht_lookup(attrtab, name); 814 if (a == NULL) { 815 *ra = NULL; 816 return (0); 817 } 818 /* 819 * Check if the existing attr is only referenced, not really defined. 820 */ 821 if (a->a_deps == NULL && 822 a->a_iattr == 0 && 823 a->a_devclass == 0) { 824 *ra = a; 825 return (0); 826 } 827 return (1); 828 } 829 830 /* 831 * Recursively expand an attribute and its dependencies, checking for 832 * cycles, and invoking a callback for each attribute found. 833 */ 834 void 835 expandattr(struct attr *a, void (*callback)(struct attr *)) 836 { 837 struct attrlist *al; 838 struct attr *dep; 839 840 if (a->a_expanding) { 841 cfgerror("circular dependency on attribute `%s'", a->a_name); 842 return; 843 } 844 845 a->a_expanding = 1; 846 847 /* First expand all of this attribute's dependencies. */ 848 for (al = a->a_deps; al != NULL; al = al->al_next) { 849 dep = al->al_this; 850 expandattr(dep, callback); 851 } 852 853 /* ...and now invoke the callback for ourself. */ 854 if (callback != NULL) 855 (*callback)(a); 856 857 a->a_expanding = 0; 858 } 859 860 /* 861 * Set the major device number for a device, so that it can be used 862 * as a root/dumps "on" device in a configuration. 863 */ 864 void 865 setmajor(struct devbase *d, devmajor_t n) 866 { 867 868 if (d != &errdev && d->d_major != NODEVMAJOR) 869 cfgerror("device `%s' is already major %d", 870 d->d_name, d->d_major); 871 else 872 d->d_major = n; 873 } 874 875 const char * 876 major2name(devmajor_t maj) 877 { 878 struct devbase *dev; 879 struct devm *dm; 880 881 if (!do_devsw) { 882 TAILQ_FOREACH(dev, &allbases, d_next) { 883 if (dev->d_major == maj) 884 return (dev->d_name); 885 } 886 } else { 887 TAILQ_FOREACH(dm, &alldevms, dm_next) { 888 if (dm->dm_bmajor == maj) 889 return (dm->dm_name); 890 } 891 } 892 return (NULL); 893 } 894 895 devmajor_t 896 dev2major(struct devbase *dev) 897 { 898 struct devm *dm; 899 900 if (!do_devsw) 901 return (dev->d_major); 902 903 TAILQ_FOREACH(dm, &alldevms, dm_next) { 904 if (strcmp(dm->dm_name, dev->d_name) == 0) 905 return (dm->dm_bmajor); 906 } 907 return (NODEVMAJOR); 908 } 909 910 /* 911 * Make a string description of the device at maj/min. 912 */ 913 static const char * 914 makedevstr(devmajor_t maj, devminor_t min) 915 { 916 const char *devicename; 917 char buf[32]; 918 919 devicename = major2name(maj); 920 if (devicename == NULL) 921 (void)snprintf(buf, sizeof(buf), "<%d/%d>", maj, min); 922 else 923 (void)snprintf(buf, sizeof(buf), "%s%d%c", devicename, 924 min / maxpartitions, (min % maxpartitions) + 'a'); 925 926 return (intern(buf)); 927 } 928 929 /* 930 * Map things like "ra0b" => makedev(major("ra"), 0*maxpartitions + 'b'-'a'). 931 * Handle the case where the device number is given but there is no 932 * corresponding name, and map NULL to the default. 933 */ 934 static int 935 resolve(struct nvlist **nvp, const char *name, const char *what, 936 struct nvlist *dflt, int part) 937 { 938 struct nvlist *nv; 939 struct devbase *dev; 940 const char *cp; 941 devmajor_t maj; 942 devminor_t min; 943 size_t i, l; 944 int unit; 945 char buf[NAMESIZE]; 946 947 if ((part -= 'a') >= maxpartitions || part < 0) 948 panic("%s: Bad partition %c", __func__, part); 949 if ((nv = *nvp) == NULL) { 950 dev_t d = NODEV; 951 /* 952 * Apply default. Easiest to do this by number. 953 * Make sure to retain NODEVness, if this is dflt's disposition. 954 */ 955 if ((dev_t)dflt->nv_num != NODEV) { 956 maj = major(dflt->nv_num); 957 min = ((minor(dflt->nv_num) / maxpartitions) * 958 maxpartitions) + part; 959 d = makedev(maj, min); 960 cp = makedevstr(maj, min); 961 } else 962 cp = NULL; 963 *nvp = nv = newnv(NULL, cp, NULL, (long long)d, NULL); 964 } 965 if ((dev_t)nv->nv_num != NODEV) { 966 /* 967 * By the numbers. Find the appropriate major number 968 * to make a name. 969 */ 970 maj = major(nv->nv_num); 971 min = minor(nv->nv_num); 972 nv->nv_str = makedevstr(maj, min); 973 return (0); 974 } 975 976 if (nv->nv_str == NULL || nv->nv_str == s_qmark) 977 /* 978 * Wildcarded or unspecified; leave it as NODEV. 979 */ 980 return (0); 981 982 if (nv->nv_ptr != NULL && strcmp(nv->nv_ptr, "spec") == 0) 983 /* 984 * spec string, interpreted by kernel 985 */ 986 return (0); 987 988 /* 989 * The normal case: things like "ra2b". Check for partition 990 * suffix, remove it if there, and split into name ("ra") and 991 * unit (2). 992 */ 993 l = i = strlen(nv->nv_str); 994 cp = &nv->nv_str[l]; 995 if (l > 1 && *--cp >= 'a' && *cp < 'a' + maxpartitions && 996 isdigit((unsigned char)cp[-1])) { 997 l--; 998 part = *cp - 'a'; 999 } 1000 cp = nv->nv_str; 1001 if (split(cp, l, buf, sizeof buf, &unit)) { 1002 cfgerror("%s: invalid %s device name `%s'", name, what, cp); 1003 return (1); 1004 } 1005 dev = ht_lookup(devbasetab, intern(buf)); 1006 if (dev == NULL) { 1007 cfgerror("%s: device `%s' does not exist", name, buf); 1008 return (1); 1009 } 1010 1011 /* 1012 * Check for the magic network interface attribute, and 1013 * don't bother making a device number. 1014 */ 1015 if (has_attr(dev->d_attrs, s_ifnet)) { 1016 nv->nv_num = (long long)NODEV; 1017 nv->nv_ifunit = unit; /* XXX XXX XXX */ 1018 } else { 1019 maj = dev2major(dev); 1020 if (maj == NODEVMAJOR) { 1021 cfgerror("%s: can't make %s device from `%s'", 1022 name, what, nv->nv_str); 1023 return (1); 1024 } 1025 nv->nv_num = (long long)makedev(maj, unit * maxpartitions + part); 1026 } 1027 1028 nv->nv_name = dev->d_name; 1029 return (0); 1030 } 1031 1032 /* 1033 * Add a completed configuration to the list. 1034 */ 1035 void 1036 addconf(struct config *cf0) 1037 { 1038 struct config *cf; 1039 const char *name; 1040 1041 name = cf0->cf_name; 1042 cf = ecalloc(1, sizeof *cf); 1043 if (ht_insert(cfhashtab, name, cf)) { 1044 cfgerror("configuration `%s' already defined", name); 1045 free(cf); 1046 goto bad; 1047 } 1048 *cf = *cf0; 1049 1050 /* 1051 * Resolve the root device. 1052 */ 1053 if (cf->cf_root == NULL) { 1054 cfgerror("%s: no root device specified", name); 1055 goto bad; 1056 } 1057 if (cf->cf_root && cf->cf_root->nv_str != s_qmark) { 1058 struct nvlist *nv; 1059 nv = cf->cf_root; 1060 if (resolve(&cf->cf_root, name, "root", nv, 'a')) 1061 goto bad; 1062 } 1063 1064 /* 1065 * Resolve the dump device. 1066 */ 1067 if (cf->cf_dump == NULL || cf->cf_dump->nv_str == s_qmark) { 1068 /* 1069 * Wildcarded dump device is equivalent to unspecified. 1070 */ 1071 cf->cf_dump = NULL; 1072 } else if (cf->cf_dump->nv_str == s_none) { 1073 /* 1074 * Operator has requested that no dump device should be 1075 * configured; do nothing. 1076 */ 1077 } else { 1078 if (resolve(&cf->cf_dump, name, "dumps", cf->cf_dump, 'b')) 1079 goto bad; 1080 } 1081 1082 /* Wildcarded fstype is `unspecified'. */ 1083 if (cf->cf_fstype == s_qmark) 1084 cf->cf_fstype = NULL; 1085 1086 TAILQ_INSERT_TAIL(&allcf, cf, cf_next); 1087 return; 1088 bad: 1089 nvfreel(cf0->cf_root); 1090 nvfreel(cf0->cf_dump); 1091 } 1092 1093 void 1094 setconf(struct nvlist **npp, const char *what, struct nvlist *v) 1095 { 1096 1097 if (*npp != NULL) { 1098 cfgerror("duplicate %s specification", what); 1099 nvfreel(v); 1100 } else 1101 *npp = v; 1102 } 1103 1104 void 1105 delconf(const char *name, int nowarn) 1106 { 1107 struct config *cf; 1108 1109 CFGDBG(5, "deselecting config `%s'", name); 1110 if (ht_lookup(cfhashtab, name) == NULL) { 1111 if (!nowarn) 1112 cfgerror("configuration `%s' undefined", name); 1113 return; 1114 } 1115 (void)ht_remove(cfhashtab, name); 1116 1117 TAILQ_FOREACH(cf, &allcf, cf_next) 1118 if (!strcmp(cf->cf_name, name)) 1119 break; 1120 if (cf == NULL) 1121 panic("%s: lost configuration for %s", __func__, name); 1122 1123 TAILQ_REMOVE(&allcf, cf, cf_next); 1124 } 1125 1126 void 1127 setfstype(const char **fstp, const char *v) 1128 { 1129 1130 if (*fstp != NULL) { 1131 cfgerror("multiple fstype specifications"); 1132 return; 1133 } 1134 1135 if (v != s_qmark && OPT_FSOPT(v)) { 1136 cfgerror("\"%s\" is not a configured file system", v); 1137 return; 1138 } 1139 1140 *fstp = v; 1141 } 1142 1143 static struct devi * 1144 newdevi(const char *name, int unit, struct devbase *d) 1145 { 1146 struct devi *i; 1147 1148 i = ecalloc(1, sizeof *i); 1149 i->i_name = name; 1150 i->i_unit = unit; 1151 i->i_base = d; 1152 i->i_bsame = NULL; 1153 i->i_asame = NULL; 1154 i->i_alias = NULL; 1155 i->i_at = NULL; 1156 i->i_pspec = NULL; 1157 i->i_atdeva = NULL; 1158 i->i_locs = NULL; 1159 i->i_cfflags = 0; 1160 i->i_lineno = currentline(); 1161 i->i_srcfile = yyfile; 1162 i->i_active = DEVI_ORPHAN; /* Proper analysis comes later */ 1163 i->i_level = devilevel; 1164 i->i_pseudoroot = 0; 1165 if (unit >= d->d_umax) 1166 d->d_umax = unit + 1; 1167 return (i); 1168 } 1169 1170 static struct attr * 1171 finddevattr(const char *name, const char *at, struct devbase *ib, 1172 struct devbase **ab, int *atunit) 1173 { 1174 const char *cp; 1175 char atbuf[NAMESIZE]; 1176 struct attrlist *al; 1177 struct attr *attr; 1178 1179 if (at == NULL) { 1180 *ab = NULL; 1181 *atunit = -1; 1182 return &errattr; /* a convenient "empty" attr */ 1183 } 1184 if (split(at, strlen(at), atbuf, sizeof atbuf, atunit)) { 1185 cfgerror("invalid attachment name `%s'", at); 1186 /* (void)getdevi(name); -- ??? */ 1187 return NULL; 1188 } 1189 1190 /* 1191 * Devices can attach to two types of things: Attributes, 1192 * and other devices (which have the appropriate attributes 1193 * to allow attachment). 1194 * 1195 * (1) If we're attached to an attribute, then we don't need 1196 * look at the parent base device to see what attributes 1197 * it has, and make sure that we can attach to them. 1198 * 1199 * (2) If we're attached to a real device (i.e. named in 1200 * the config file), we want to remember that so that 1201 * at cross-check time, if the device we're attached to 1202 * is missing but other devices which also provide the 1203 * attribute are present, we don't get a false "OK." 1204 * 1205 * (3) If the thing we're attached to is an attribute 1206 * but is actually named in the config file, we still 1207 * have to remember its devbase. 1208 */ 1209 cp = intern(atbuf); 1210 1211 /* Figure out parent's devbase, to satisfy case (3). */ 1212 *ab = ht_lookup(devbasetab, cp); 1213 1214 /* Find out if it's an attribute. */ 1215 attr = ht_lookup(attrtab, cp); 1216 1217 /* Make sure we're _really_ attached to the attr. Case (1). */ 1218 if (attr != NULL && onlist(attr->a_devs, ib)) 1219 return attr; 1220 1221 /* 1222 * Else a real device, and not just an attribute. Case (2). 1223 * 1224 * Have to work a bit harder to see whether we have 1225 * something like "tg0 at esp0" (where esp is merely 1226 * not an attribute) or "tg0 at nonesuch0" (where 1227 * nonesuch is not even a device). 1228 */ 1229 if (*ab == NULL) { 1230 cfgerror("%s at %s: `%s' unknown", name, at, atbuf); 1231 return NULL; 1232 } 1233 1234 /* 1235 * See if the named parent carries an attribute 1236 * that allows it to supervise device ib. 1237 */ 1238 for (al = (*ab)->d_attrs; al != NULL; al = al->al_next) { 1239 attr = al->al_this; 1240 if (onlist(attr->a_devs, ib)) 1241 return attr; 1242 } 1243 cfgerror("`%s' cannot attach to `%s'", ib->d_name, atbuf); 1244 return NULL; 1245 } 1246 1247 /* 1248 * Add the named device as attaching to the named attribute (or perhaps 1249 * another device instead) plus unit number. 1250 */ 1251 void 1252 adddev(const char *name, const char *at, struct loclist *loclist, int flags) 1253 { 1254 struct devi *i; /* the new instance */ 1255 struct pspec *p; /* and its pspec */ 1256 struct attr *attr; /* attribute that allows attach */ 1257 struct devbase *ib; /* i->i_base */ 1258 struct devbase *ab; /* not NULL => at another dev */ 1259 struct deva *iba; /* devbase attachment used */ 1260 struct deva *lastiba; 1261 int atunit, first; 1262 1263 lastiba = NULL; 1264 if ((i = getdevi(name)) == NULL) 1265 goto bad; 1266 ib = i->i_base; 1267 attr = finddevattr(name, at, ib, &ab, &atunit); 1268 if (attr == NULL) { 1269 i->i_active = DEVI_BROKEN; 1270 goto bad; 1271 } 1272 1273 for (lastiba = ib->d_ahead; lastiba; lastiba = iba->d_bsame) { 1274 for (iba = lastiba; iba != NULL; iba = iba->d_bsame) 1275 if (onlist(iba->d_atlist, 1276 attr == &errattr ? NULL : attr)) 1277 break; 1278 1279 first = lastiba == ib->d_ahead; 1280 if (iba == NULL) { 1281 if (!first) 1282 goto bad; 1283 if (attr != &errattr) { 1284 panic("%s: can't figure out attachment", 1285 __func__); 1286 } else { 1287 cfgerror("`%s' cannot attach to the root", 1288 ib->d_name); 1289 i->i_active = DEVI_BROKEN; 1290 } 1291 } 1292 // get a new one if it is not the first time 1293 if (!first && (i = getdevi(name)) == NULL) 1294 goto bad; 1295 1296 if (attr != &errattr) { 1297 /* 1298 * Find the parent spec. If a matching one has not 1299 * yet been created, create one. 1300 * 1301 * XXX: This creates multiple pspecs that look the 1302 * same in the config file and could be merged. 1303 */ 1304 p = getpspec(attr, ab, atunit, first); 1305 p->p_devs = newnv(NULL, NULL, i, 0, p->p_devs); 1306 } else 1307 p = NULL; 1308 1309 if ((i->i_locs = fixloc(name, attr, loclist)) == NULL) { 1310 i->i_active = DEVI_BROKEN; 1311 goto bad; 1312 } 1313 i->i_at = at; 1314 i->i_pspec = p; 1315 i->i_atdeva = iba; 1316 i->i_cfflags = flags; 1317 CFGDBG(3, "devi `%s' at '%s' added", i->i_name, iba->d_name); 1318 1319 *iba->d_ipp = i; 1320 iba->d_ipp = &i->i_asame; 1321 } 1322 1323 /* all done, fall into ... */ 1324 bad: 1325 loclist_destroy(loclist); 1326 return; 1327 } 1328 1329 void 1330 deldevi(const char *name, const char *at, int nowarn) 1331 { 1332 struct devi *firsti, *i; 1333 struct devbase *d; 1334 int unit; 1335 char base[NAMESIZE]; 1336 1337 CFGDBG(5, "deselecting devi `%s'", name); 1338 if (split(name, strlen(name), base, sizeof base, &unit)) { 1339 if (!nowarn) { 1340 cfgerror("invalid device name `%s'", name); 1341 return; 1342 } 1343 } 1344 d = ht_lookup(devbasetab, intern(base)); 1345 if (d == NULL) { 1346 if (!nowarn) 1347 cfgerror("%s: unknown device `%s'", name, base); 1348 return; 1349 } 1350 if (d->d_ispseudo) { 1351 cfgerror("%s: %s is a pseudo-device", name, base); 1352 return; 1353 } 1354 if ((firsti = ht_lookup(devitab, name)) == NULL) { 1355 cfgerror("`%s' not defined", name); 1356 return; 1357 } 1358 if (at == NULL && firsti->i_at == NULL) { 1359 /* 'at root' */ 1360 remove_devi(firsti); 1361 return; 1362 } else if (at != NULL) 1363 for (i = firsti; i != NULL; i = i->i_alias) 1364 if (i->i_active != DEVI_BROKEN && 1365 strcmp(at, i->i_at) == 0) { 1366 remove_devi(i); 1367 return; 1368 } 1369 cfgerror("`%s' at `%s' not found", name, at ? at : "root"); 1370 } 1371 1372 static void 1373 remove_pspec(struct devi *i) 1374 { 1375 struct pspec *p = i->i_pspec; 1376 struct nvlist *nv, *onv; 1377 1378 if (p == NULL) 1379 return; 1380 1381 /* Double-linked nvlist anyone? */ 1382 for (nv = p->p_devs; nv->nv_next != NULL; nv = nv->nv_next) { 1383 if (nv->nv_next && nv->nv_next->nv_ptr == i) { 1384 onv = nv->nv_next; 1385 nv->nv_next = onv->nv_next; 1386 nvfree(onv); 1387 break; 1388 } 1389 if (nv->nv_ptr == i) { 1390 /* nv is p->p_devs in that case */ 1391 p->p_devs = nv->nv_next; 1392 nvfree(nv); 1393 break; 1394 } 1395 } 1396 if (p->p_devs == NULL) 1397 TAILQ_REMOVE(&allpspecs, p, p_list); 1398 } 1399 1400 static void 1401 remove_devi(struct devi *i) 1402 { 1403 struct devbase *d = i->i_base; 1404 struct devi *f, *j, **ppi; 1405 struct deva *iba; 1406 1407 CFGDBG(5, "removing devi `%s'", i->i_name); 1408 f = ht_lookup(devitab, i->i_name); 1409 if (f == NULL) 1410 panic("%s: instance %s disappeared from devitab", __func__, 1411 i->i_name); 1412 1413 if (i->i_active == DEVI_BROKEN) { 1414 cfgerror("not removing broken instance `%s'", i->i_name); 1415 return; 1416 } 1417 1418 /* 1419 * We have the device instance, i. 1420 * We have to: 1421 * - delete the alias 1422 * 1423 * If the devi was an alias of an already listed devi, all is 1424 * good we don't have to do more. 1425 * If it was the first alias, we have to replace i's entry in 1426 * d's list by its first alias. 1427 * If it was the only entry, we must remove i's entry from d's 1428 * list. 1429 */ 1430 if (i != f) { 1431 for (j = f; j->i_alias != i; j = j->i_alias) 1432 continue; 1433 j->i_alias = i->i_alias; 1434 } else { 1435 if (i->i_alias == NULL) { 1436 /* No alias, must unlink the entry from devitab */ 1437 ht_remove(devitab, i->i_name); 1438 j = i->i_bsame; 1439 } else { 1440 /* Or have the first alias replace i in d's list */ 1441 i->i_alias->i_bsame = i->i_bsame; 1442 j = i->i_alias; 1443 if (i == f) 1444 ht_replace(devitab, i->i_name, i->i_alias); 1445 } 1446 1447 /* 1448 * - remove/replace the instance from the devbase's list 1449 * 1450 * A double-linked list would make this much easier. Oh, well, 1451 * what is done is done. 1452 */ 1453 for (ppi = &d->d_ihead; 1454 *ppi != NULL && *ppi != i && (*ppi)->i_bsame != i; 1455 ppi = &(*ppi)->i_bsame) 1456 continue; 1457 if (*ppi == NULL) 1458 panic("%s: dev (%s) doesn't list the devi (%s at %s)", 1459 __func__, d->d_name, i->i_name, i->i_at); 1460 f = *ppi; 1461 if (f == i) 1462 /* That implies d->d_ihead == i */ 1463 *ppi = j; 1464 else 1465 (*ppi)->i_bsame = j; 1466 if (d->d_ipp == &i->i_bsame) { 1467 if (i->i_alias == NULL) { 1468 if (f == i) 1469 d->d_ipp = &d->d_ihead; 1470 else 1471 d->d_ipp = &f->i_bsame; 1472 } else 1473 d->d_ipp = &i->i_alias->i_bsame; 1474 } 1475 } 1476 /* 1477 * - delete the attachment instance 1478 */ 1479 iba = i->i_atdeva; 1480 for (ppi = &iba->d_ihead; 1481 *ppi != NULL && *ppi != i && (*ppi)->i_asame != i; 1482 ppi = &(*ppi)->i_asame) 1483 continue; 1484 if (*ppi == NULL) 1485 panic("%s: deva (%s) doesn't list the devi (%s)", __func__, 1486 iba->d_name, i->i_name); 1487 f = *ppi; 1488 if (f == i) 1489 /* That implies iba->d_ihead == i */ 1490 *ppi = i->i_asame; 1491 else 1492 (*ppi)->i_asame = i->i_asame; 1493 if (iba->d_ipp == &i->i_asame) { 1494 if (f == i) 1495 iba->d_ipp = &iba->d_ihead; 1496 else 1497 iba->d_ipp = &f->i_asame; 1498 } 1499 /* 1500 * - delete the pspec 1501 */ 1502 remove_pspec(i); 1503 1504 /* 1505 * - delete the alldevi entry 1506 */ 1507 TAILQ_REMOVE(&alldevi, i, i_next); 1508 ndevi--; 1509 /* 1510 * Put it in deaddevitab 1511 * 1512 * Each time a devi is removed, devilevel is increased so that later on 1513 * it is possible to tell if an instance was added before or after the 1514 * removal of its parent. 1515 * 1516 * For active instances, i_level contains the number of devi removed so 1517 * far, and for dead devis, it contains its index. 1518 */ 1519 i->i_level = devilevel++; 1520 i->i_alias = NULL; 1521 f = ht_lookup(deaddevitab, i->i_name); 1522 if (f == NULL) { 1523 if (ht_insert(deaddevitab, i->i_name, i)) 1524 panic("%s: can't add %s to deaddevitab", __func__, 1525 i->i_name); 1526 } else { 1527 for (j = f; j->i_alias != NULL; j = j->i_alias) 1528 continue; 1529 j->i_alias = i; 1530 } 1531 /* 1532 * - reconstruct d->d_umax 1533 */ 1534 d->d_umax = 0; 1535 for (i = d->d_ihead; i != NULL; i = i->i_bsame) 1536 if (i->i_unit >= d->d_umax) 1537 d->d_umax = i->i_unit + 1; 1538 } 1539 1540 void 1541 deldeva(const char *at, int nowarn) 1542 { 1543 int unit; 1544 const char *cp; 1545 struct devbase *d, *ad; 1546 struct devi *i, *j; 1547 struct attr *a; 1548 struct pspec *p; 1549 struct nvlist *nv, *stack = NULL; 1550 1551 if (at == NULL) { 1552 TAILQ_FOREACH(i, &alldevi, i_next) 1553 if (i->i_at == NULL) 1554 stack = newnv(NULL, NULL, i, 0, stack); 1555 } else { 1556 size_t l; 1557 1558 CFGDBG(5, "deselecting deva `%s'", at); 1559 if (at[0] == '\0') 1560 goto out; 1561 1562 l = strlen(at) - 1; 1563 if (at[l] == '?' || isdigit((unsigned char)at[l])) { 1564 char base[NAMESIZE]; 1565 1566 if (split(at, l+1, base, sizeof base, &unit)) { 1567 out: 1568 cfgerror("invalid attachment name `%s'", at); 1569 return; 1570 } 1571 cp = intern(base); 1572 } else { 1573 cp = intern(at); 1574 unit = STAR; 1575 } 1576 1577 ad = ht_lookup(devbasetab, cp); 1578 a = ht_lookup(attrtab, cp); 1579 if (a == NULL) { 1580 cfgerror("unknown attachment attribute or device `%s'", 1581 cp); 1582 return; 1583 } 1584 if (!a->a_iattr) { 1585 cfgerror("plain attribute `%s' cannot have children", 1586 a->a_name); 1587 return; 1588 } 1589 1590 /* 1591 * remove_devi() makes changes to the devbase's list and the 1592 * alias list, * so the actual deletion of the instances must 1593 * be delayed. 1594 */ 1595 for (nv = a->a_devs; nv != NULL; nv = nv->nv_next) { 1596 d = nv->nv_ptr; 1597 for (i = d->d_ihead; i != NULL; i = i->i_bsame) 1598 for (j = i; j != NULL; j = j->i_alias) { 1599 /* Ignore devices at root */ 1600 if (j->i_at == NULL) 1601 continue; 1602 p = j->i_pspec; 1603 /* 1604 * There are three cases: 1605 * 1606 * 1. unit is not STAR. Consider 'at' 1607 * to be explicit, even if it 1608 * references an interface 1609 * attribute. 1610 * 1611 * 2. unit is STAR and 'at' references 1612 * a real device. Look for pspec 1613 * that have a matching p_atdev 1614 * field. 1615 * 1616 * 3. unit is STAR and 'at' references 1617 * an interface attribute. Look 1618 * for pspec that have a matching 1619 * p_iattr field. 1620 */ 1621 if ((unit != STAR && /* Case */ 1622 !strcmp(j->i_at, at)) || /* 1 */ 1623 (unit == STAR && 1624 ((ad != NULL && /* Case */ 1625 p->p_atdev == ad) || /* 2 */ 1626 (ad == NULL && /* Case */ 1627 p->p_iattr == a)))) /* 3 */ 1628 stack = newnv(NULL, NULL, j, 0, 1629 stack); 1630 } 1631 } 1632 } 1633 1634 devcleanup(stack); 1635 } 1636 1637 void 1638 deldev(const char *name, int nowarn) 1639 { 1640 size_t l; 1641 struct devi *firsti, *i; 1642 struct nvlist *stack = NULL; 1643 1644 CFGDBG(5, "deselecting dev `%s'", name); 1645 if (name[0] == '\0') 1646 goto out; 1647 1648 l = strlen(name) - 1; 1649 if (name[l] == '*' || isdigit((unsigned char)name[l])) { 1650 /* `no mydev0' or `no mydev*' */ 1651 firsti = ht_lookup(devitab, name); 1652 if (firsti == NULL) { 1653 out: 1654 if (!nowarn) 1655 cfgerror("unknown instance %s", name); 1656 return; 1657 } 1658 for (i = firsti; i != NULL; i = i->i_alias) 1659 stack = newnv(NULL, NULL, i, 0, stack); 1660 } else { 1661 struct devbase *d = ht_lookup(devbasetab, name); 1662 1663 if (d == NULL) { 1664 cfgerror("unknown device %s", name); 1665 return; 1666 } 1667 if (d->d_ispseudo) { 1668 cfgerror("%s is a pseudo-device; " 1669 "use \"no pseudo-device %s\" instead", name, 1670 name); 1671 return; 1672 } 1673 stack = makedevstack(d); 1674 } 1675 1676 devcleanup(stack); 1677 } 1678 1679 /* 1680 * Insert given device "name" into devroottab. In case "name" 1681 * designates a pure interface attribute, create a fake device 1682 * instance for the attribute and insert that into the roottab 1683 * (this scheme avoids mucking around with the orphanage analysis). 1684 */ 1685 void 1686 addpseudoroot(const char *name) 1687 { 1688 char buf[NAMESIZE]; 1689 int unit; 1690 struct attr *attr; 1691 struct devi *i; 1692 struct deva *iba; 1693 struct devbase *ib; 1694 1695 if (split(name, strlen(name), buf, sizeof(buf), &unit)) { 1696 cfgerror("invalid pseudo-root name `%s'", name); 1697 return; 1698 } 1699 1700 /* 1701 * Prefer device because devices with locators define an 1702 * implicit interface attribute. However, if a device is 1703 * not available, try to attach to the interface attribute. 1704 * This makes sure adddev() doesn't get confused when we 1705 * are really attaching to a device (alternatively we maybe 1706 * could specify a non-NULL atlist to defdevattach() below). 1707 */ 1708 ib = ht_lookup(devbasetab, intern(buf)); 1709 if (ib == NULL) { 1710 struct devbase *fakedev; 1711 char fakename[NAMESIZE]; 1712 1713 attr = ht_lookup(attrtab, intern(buf)); 1714 if (!(attr && attr->a_iattr)) { 1715 cfgerror("pseudo-root `%s' not available", name); 1716 return; 1717 } 1718 1719 /* 1720 * here we cheat a bit: create a fake devbase with the 1721 * interface attribute and instantiate it. quick, cheap, 1722 * dirty & bad for you, much like the stuff in the fridge. 1723 * and, it works, since the pseudoroot device is not included 1724 * in ioconf, just used by config to make sure we start from 1725 * the right place. 1726 */ 1727 snprintf(fakename, sizeof(fakename), "%s_devattrs", buf); 1728 fakedev = getdevbase(intern(fakename)); 1729 fakedev->d_isdef = 1; 1730 fakedev->d_ispseudo = 0; 1731 fakedev->d_attrs = attrlist_cons(NULL, attr); 1732 defdevattach(NULL, fakedev, NULL, NULL); 1733 1734 if (unit == STAR) 1735 snprintf(buf, sizeof(buf), "%s*", fakename); 1736 else 1737 snprintf(buf, sizeof(buf), "%s%d", fakename, unit); 1738 name = buf; 1739 } 1740 1741 /* ok, everything should be set up, so instantiate a fake device */ 1742 i = getdevi(name); 1743 if (i == NULL) 1744 panic("%s: device `%s' expected to be present", __func__, 1745 name); 1746 ib = i->i_base; 1747 iba = ib->d_ahead; 1748 1749 i->i_atdeva = iba; 1750 i->i_cfflags = 0; 1751 i->i_locs = fixloc(name, &errattr, NULL); 1752 i->i_pseudoroot = 1; 1753 i->i_active = DEVI_ORPHAN; /* set active by kill_orphans() */ 1754 1755 *iba->d_ipp = i; 1756 iba->d_ipp = &i->i_asame; 1757 1758 ht_insert(devroottab, ib->d_name, ib); 1759 } 1760 1761 static void 1762 deldevbase(struct devbase *d) 1763 { 1764 struct devi *i; 1765 const char *name = d->d_name; 1766 1767 if (!d->d_ispseudo) { 1768 devcleanup(makedevstack(d)); 1769 return; 1770 } 1771 1772 if ((i = ht_lookup(devitab, name)) == NULL) 1773 return; 1774 1775 d->d_umax = 0; /* clear neads-count entries */ 1776 d->d_ihead = NULL; /* make sure it won't be considered active */ 1777 TAILQ_REMOVE(&allpseudo, i, i_next); 1778 if (ht_remove(devitab, name)) 1779 panic("%s: Can't remove %s from devitab", __func__, name); 1780 if (ht_insert(deaddevitab, name, i)) 1781 panic("%s: Can't add %s to deaddevitab", __func__, name); 1782 } 1783 1784 void 1785 addpseudo(const char *name, int number) 1786 { 1787 struct devbase *d; 1788 struct devi *i; 1789 1790 d = ht_lookup(devbasetab, name); 1791 if (d == NULL) { 1792 cfgerror("undefined pseudo-device %s", name); 1793 return; 1794 } 1795 if (!d->d_ispseudo) { 1796 cfgerror("%s is a real device, not a pseudo-device", name); 1797 return; 1798 } 1799 if (ht_lookup(devitab, name) != NULL) { 1800 cfgerror("`%s' already defined", name); 1801 return; 1802 } 1803 i = newdevi(name, number - 1, d); /* foo 16 => "foo0..foo15" */ 1804 if (ht_insert(devitab, name, i)) 1805 panic("%s: %s", __func__, name); 1806 /* Useful to retrieve the instance from the devbase */ 1807 d->d_ihead = i; 1808 i->i_active = DEVI_ACTIVE; 1809 TAILQ_INSERT_TAIL(&allpseudo, i, i_next); 1810 } 1811 1812 void 1813 delpseudo(const char *name, int nowarn) 1814 { 1815 struct devbase *d; 1816 1817 CFGDBG(5, "deselecting pseudo `%s'", name); 1818 d = ht_lookup(devbasetab, name); 1819 if (d == NULL) { 1820 if (!nowarn) 1821 cfgerror("undefined pseudo-device %s", name); 1822 return; 1823 } 1824 if (!d->d_ispseudo) { 1825 cfgerror("%s is a real device, not a pseudo-device", name); 1826 return; 1827 } 1828 deldevbase(d); 1829 } 1830 1831 void 1832 adddevm(const char *name, devmajor_t cmajor, devmajor_t bmajor, 1833 struct condexpr *cond, struct nvlist *nv_nodes) 1834 { 1835 struct devm *dm; 1836 1837 if (cmajor != NODEVMAJOR && (cmajor < 0 || cmajor >= 4096)) { 1838 cfgerror("character major %d is invalid", cmajor); 1839 condexpr_destroy(cond); 1840 nvfreel(nv_nodes); 1841 return; 1842 } 1843 1844 if (bmajor != NODEVMAJOR && (bmajor < 0 || bmajor >= 4096)) { 1845 cfgerror("block major %d is invalid", bmajor); 1846 condexpr_destroy(cond); 1847 nvfreel(nv_nodes); 1848 return; 1849 } 1850 if (cmajor == NODEVMAJOR && bmajor == NODEVMAJOR) { 1851 cfgerror("both character/block majors are not specified"); 1852 condexpr_destroy(cond); 1853 nvfreel(nv_nodes); 1854 return; 1855 } 1856 1857 dm = ecalloc(1, sizeof(*dm)); 1858 dm->dm_srcfile = yyfile; 1859 dm->dm_srcline = currentline(); 1860 dm->dm_name = name; 1861 dm->dm_cmajor = cmajor; 1862 dm->dm_bmajor = bmajor; 1863 dm->dm_opts = cond; 1864 dm->dm_devnodes = nv_nodes; 1865 1866 TAILQ_INSERT_TAIL(&alldevms, dm, dm_next); 1867 1868 maxcdevm = MAX(maxcdevm, dm->dm_cmajor); 1869 maxbdevm = MAX(maxbdevm, dm->dm_bmajor); 1870 } 1871 1872 int 1873 fixdevis(void) 1874 { 1875 const char *msg; 1876 struct devi *i; 1877 struct pspec *p; 1878 int error = 0; 1879 1880 TAILQ_FOREACH(i, &alldevi, i_next) { 1881 CFGDBG(3, "fixing devis `%s'", i->i_name); 1882 if (i->i_active == DEVI_ACTIVE) 1883 selectbase(i->i_base, i->i_atdeva); 1884 else if (i->i_active == DEVI_ORPHAN) { 1885 /* 1886 * At this point, we can't have instances for which 1887 * i_at or i_pspec are NULL. 1888 */ 1889 ++error; 1890 p = i->i_pspec; 1891 msg = p == NULL ? "no parent" : 1892 (p->p_atunit == WILD ? "nothing matching" : "no"); 1893 cfgxerror(i->i_srcfile, i->i_lineno, 1894 "`%s at %s' is orphaned (%s `%s' found)", 1895 i->i_name, i->i_at, msg, i->i_at); 1896 } else if (vflag && i->i_active == DEVI_IGNORED) 1897 cfgxwarn(i->i_srcfile, i->i_lineno, "ignoring " 1898 "explicitly orphaned instance `%s at %s'", 1899 i->i_name, i->i_at); 1900 } 1901 1902 if (error) 1903 return error; 1904 1905 TAILQ_FOREACH(i, &allpseudo, i_next) 1906 if (i->i_active == DEVI_ACTIVE) 1907 selectbase(i->i_base, NULL); 1908 return 0; 1909 } 1910 1911 /* 1912 * Look up a parent spec, creating a new one if it does not exist. 1913 */ 1914 static struct pspec * 1915 getpspec(struct attr *attr, struct devbase *ab, int atunit, int first) 1916 { 1917 struct pspec *p; 1918 int inst = npspecs; 1919 int ref = 1; 1920 1921 TAILQ_FOREACH(p, &allpspecs, p_list) { 1922 if (p->p_iattr == attr && p->p_atdev == ab && 1923 p->p_atunit == atunit) { 1924 p->p_ref++; 1925 if (first) 1926 return p; 1927 else { 1928 inst = p->p_inst; 1929 ref = p->p_ref; 1930 } 1931 1932 } 1933 } 1934 1935 p = ecalloc(1, sizeof(*p)); 1936 1937 p->p_iattr = attr; 1938 p->p_atdev = ab; 1939 p->p_atunit = atunit; 1940 p->p_inst = inst; 1941 if (inst == npspecs) 1942 npspecs++; 1943 p->p_active = 0; 1944 p->p_ref = ref; 1945 1946 TAILQ_INSERT_TAIL(&allpspecs, p, p_list); 1947 1948 return (p); 1949 } 1950 1951 /* 1952 * Define a new instance of a specific device. 1953 */ 1954 static struct devi * 1955 getdevi(const char *name) 1956 { 1957 struct devi *i, *firsti; 1958 struct devbase *d; 1959 int unit; 1960 char base[NAMESIZE]; 1961 1962 if (split(name, strlen(name), base, sizeof base, &unit)) { 1963 cfgerror("invalid device name `%s'", name); 1964 return (NULL); 1965 } 1966 d = ht_lookup(devbasetab, intern(base)); 1967 if (d == NULL) { 1968 cfgerror("%s: unknown device `%s'", name, base); 1969 return (NULL); 1970 } 1971 if (d->d_ispseudo) { 1972 cfgerror("%s: %s is a pseudo-device", name, base); 1973 return (NULL); 1974 } 1975 firsti = ht_lookup(devitab, name); 1976 i = newdevi(name, unit, d); 1977 if (firsti == NULL) { 1978 if (ht_insert(devitab, name, i)) 1979 panic("%s: %s", __func__, name); 1980 *d->d_ipp = i; 1981 d->d_ipp = &i->i_bsame; 1982 } else { 1983 while (firsti->i_alias) 1984 firsti = firsti->i_alias; 1985 firsti->i_alias = i; 1986 } 1987 TAILQ_INSERT_TAIL(&alldevi, i, i_next); 1988 ndevi++; 1989 return (i); 1990 } 1991 1992 static const char * 1993 concat(const char *name, int c) 1994 { 1995 size_t len; 1996 char buf[NAMESIZE]; 1997 1998 len = strlen(name); 1999 if (len + 2 > sizeof(buf)) { 2000 cfgerror("device name `%s%c' too long", name, c); 2001 len = sizeof(buf) - 2; 2002 } 2003 memmove(buf, name, len); 2004 buf[len] = (char)c; 2005 buf[len + 1] = '\0'; 2006 return (intern(buf)); 2007 } 2008 2009 const char * 2010 starref(const char *name) 2011 { 2012 2013 return (concat(name, '*')); 2014 } 2015 2016 const char * 2017 wildref(const char *name) 2018 { 2019 2020 return (concat(name, '?')); 2021 } 2022 2023 /* 2024 * Split a name like "foo0" into base name (foo) and unit number (0). 2025 * Return 0 on success. To make this useful for names like "foo0a", 2026 * the length of the "foo0" part is one of the arguments. 2027 */ 2028 static int 2029 split(const char *name, size_t nlen, char *base, size_t bsize, int *aunit) 2030 { 2031 const char *cp; 2032 int c; 2033 size_t l; 2034 2035 l = nlen; 2036 if (l < 2 || l >= bsize || isdigit((unsigned char)*name)) 2037 return (1); 2038 c = (u_char)name[--l]; 2039 if (!isdigit(c)) { 2040 if (c == '*') 2041 *aunit = STAR; 2042 else if (c == '?') 2043 *aunit = WILD; 2044 else 2045 return (1); 2046 } else { 2047 cp = &name[l]; 2048 while (isdigit((unsigned char)cp[-1])) 2049 l--, cp--; 2050 *aunit = atoi(cp); 2051 } 2052 memmove(base, name, l); 2053 base[l] = 0; 2054 return (0); 2055 } 2056 2057 void 2058 addattr(const char *name) 2059 { 2060 struct attr *a; 2061 2062 a = refattr(name); 2063 selectattr(a); 2064 } 2065 2066 void 2067 delattr(const char *name, int nowarn) 2068 { 2069 struct attr *a; 2070 2071 a = refattr(name); 2072 deselectattr(a); 2073 } 2074 2075 void 2076 selectattr(struct attr *a) 2077 { 2078 struct attrlist *al; 2079 struct attr *dep; 2080 2081 CFGDBG(5, "selecting attr `%s'", a->a_name); 2082 for (al = a->a_deps; al != NULL; al = al->al_next) { 2083 dep = al->al_this; 2084 selectattr(dep); 2085 } 2086 if (ht_insert(selecttab, a->a_name, __UNCONST(a->a_name)) == 0) 2087 nattrs++; 2088 CFGDBG(3, "attr selected `%s'", a->a_name); 2089 } 2090 2091 static int 2092 deselectattrcb2(const char *name1, const char *name2, void *v, void *arg) 2093 { 2094 struct attr *a = arg; 2095 const char *name = a->a_name; 2096 struct vtype *vt = v; 2097 2098 if (strcmp(name, name2) == 0) { 2099 delattr(name1, 0); 2100 return 0; 2101 } 2102 2103 if (!vt->attr->a_deselected) 2104 return 0; 2105 2106 switch (vt->type) { 2107 case V_ATTRIBUTE: 2108 #ifdef notyet 2109 // XXX: Loops 2110 deselectattr(vt->value); 2111 #endif 2112 break; 2113 case V_DEVICE: 2114 CFGDBG(5, "removing device `%s' with attr `%s' because attr `%s'" 2115 " is deselected", name1, name2, name); 2116 deldevbase(vt->value); 2117 break; 2118 default: 2119 abort(); 2120 } 2121 return 0; 2122 } 2123 2124 void 2125 deselectattr(struct attr *a) 2126 { 2127 CFGDBG(5, "deselecting attr `%s'", a->a_name); 2128 a->a_deselected = 1; 2129 ht_enumerate2(attrdeptab, deselectattrcb2, a); 2130 if (ht_remove(selecttab, a->a_name) == 0) 2131 nattrs--; 2132 CFGDBG(3, "attr deselected `%s'", a->a_name); 2133 } 2134 2135 static int 2136 dumpattrdepcb2(const char *name1, const char *name2, void *v, void *arg) 2137 { 2138 2139 CFGDBG(3, "attr `%s' depends on attr `%s'", name1, name2); 2140 return 0; 2141 } 2142 2143 void 2144 dependattrs(void) 2145 { 2146 2147 ht_enumerate2(attrdeptab, dumpattrdepcb2, NULL); 2148 } 2149 2150 /* 2151 * We have an instance of the base foo, so select it and all its 2152 * attributes for "optional foo". 2153 */ 2154 static void 2155 selectbase(struct devbase *d, struct deva *da) 2156 { 2157 struct attr *a; 2158 struct attrlist *al; 2159 2160 (void)ht_insert(selecttab, d->d_name, __UNCONST(d->d_name)); 2161 CFGDBG(3, "devbase selected `%s'", d->d_name); 2162 CFGDBG(5, "selecting dependencies of devbase `%s'", d->d_name); 2163 for (al = d->d_attrs; al != NULL; al = al->al_next) { 2164 a = al->al_this; 2165 expandattr(a, selectattr); 2166 } 2167 2168 struct attr *devattr; 2169 devattr = refattr(d->d_name); 2170 expandattr(devattr, selectattr); 2171 2172 if (da != NULL) { 2173 (void)ht_insert(selecttab, da->d_name, __UNCONST(da->d_name)); 2174 CFGDBG(3, "devattr selected `%s'", da->d_name); 2175 for (al = da->d_attrs; al != NULL; al = al->al_next) { 2176 a = al->al_this; 2177 expandattr(a, selectattr); 2178 } 2179 } 2180 2181 fixdev(d); 2182 } 2183 2184 /* 2185 * Is the given pointer on the given list of pointers? 2186 */ 2187 int 2188 onlist(struct nvlist *nv, void *ptr) 2189 { 2190 for (; nv != NULL; nv = nv->nv_next) 2191 if (nv->nv_ptr == ptr) 2192 return (1); 2193 return (0); 2194 } 2195 2196 static char * 2197 extend(char *p, const char *name) 2198 { 2199 size_t l; 2200 2201 l = strlen(name); 2202 memmove(p, name, l); 2203 p += l; 2204 *p++ = ','; 2205 *p++ = ' '; 2206 return (p); 2207 } 2208 2209 /* 2210 * Check that we got all required locators, and default any that are 2211 * given as "?" and have defaults. Return 0 on success. 2212 */ 2213 static const char ** 2214 fixloc(const char *name, struct attr *attr, struct loclist *got) 2215 { 2216 struct loclist *m, *n; 2217 int ord; 2218 const char **lp; 2219 int nmissing, nextra, nnodefault; 2220 char *mp, *ep, *ndp; 2221 char missing[1000], extra[1000], nodefault[1000]; 2222 static const char *nullvec[1]; 2223 2224 /* 2225 * Look for all required locators, and number the given ones 2226 * according to the required order. While we are numbering, 2227 * set default values for defaulted locators. 2228 */ 2229 if (attr->a_loclen == 0) /* e.g., "at root" */ 2230 lp = nullvec; 2231 else 2232 lp = emalloc((size_t)(attr->a_loclen + 1) * sizeof(const char *)); 2233 for (n = got; n != NULL; n = n->ll_next) 2234 n->ll_num = -1; 2235 nmissing = 0; 2236 mp = missing; 2237 /* yes, this is O(mn), but m and n should be small */ 2238 for (ord = 0, m = attr->a_locs; m != NULL; m = m->ll_next, ord++) { 2239 for (n = got; n != NULL; n = n->ll_next) { 2240 if (n->ll_name == m->ll_name) { 2241 n->ll_num = ord; 2242 break; 2243 } 2244 } 2245 if (n == NULL && m->ll_num == 0) { 2246 nmissing++; 2247 mp = extend(mp, m->ll_name); 2248 } 2249 lp[ord] = m->ll_string; 2250 } 2251 if (ord != attr->a_loclen) 2252 panic("%s: bad length", __func__); 2253 lp[ord] = NULL; 2254 nextra = 0; 2255 ep = extra; 2256 nnodefault = 0; 2257 ndp = nodefault; 2258 for (n = got; n != NULL; n = n->ll_next) { 2259 if (n->ll_num >= 0) { 2260 if (n->ll_string != NULL) 2261 lp[n->ll_num] = n->ll_string; 2262 else if (lp[n->ll_num] == NULL) { 2263 nnodefault++; 2264 ndp = extend(ndp, n->ll_name); 2265 } 2266 } else { 2267 nextra++; 2268 ep = extend(ep, n->ll_name); 2269 } 2270 } 2271 if (nextra) { 2272 ep[-2] = 0; /* kill ", " */ 2273 cfgerror("%s: extraneous locator%s: %s", 2274 name, nextra > 1 ? "s" : "", extra); 2275 } 2276 if (nmissing) { 2277 mp[-2] = 0; 2278 cfgerror("%s: must specify %s", name, missing); 2279 } 2280 if (nnodefault) { 2281 ndp[-2] = 0; 2282 cfgerror("%s: cannot wildcard %s", name, nodefault); 2283 } 2284 if (nmissing || nnodefault) { 2285 free(lp); 2286 lp = NULL; 2287 } 2288 return (lp); 2289 } 2290 2291 void 2292 setversion(int newver) 2293 { 2294 if (newver > CONFIG_VERSION) 2295 cfgerror("your sources require a newer version of config(1) " 2296 "-- please rebuild it."); 2297 else if (newver < CONFIG_MINVERSION) 2298 cfgerror("your sources are out of date -- please update."); 2299 else 2300 version = newver; 2301 } 2302