1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright (c) 1997, by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 /*LINTLIBRARY*/ 32 33 /* 34 * getdev.c 35 * 36 * Contents: 37 * getdev() List devices that match certain criteria. 38 */ 39 40 /* 41 * Header files referenced: 42 * <sys/types.h> System Data Types 43 * <errno.h> Error handling 44 * <fcntl.h> File controlling 45 * <ctype.h> Character types 46 * <string.h> String handling 47 * <devmgmt.h> Global device-management def'ns 48 * "devtab.h" Local device-management dev'ns 49 */ 50 51 #include <sys/types.h> 52 #include <errno.h> 53 #include <fcntl.h> 54 #include <ctype.h> 55 #include <string.h> 56 #include <devmgmt.h> 57 #include "devtab.h" 58 #include <stdlib.h> 59 60 /* 61 * Local definitions 62 * NULL Nil address 63 * TRUE Boolean TRUE 64 * FALSE Boolean FALSE 65 */ 66 67 #ifndef NULL 68 #define NULL 0 69 #endif 70 71 #ifndef TRUE 72 #define TRUE ('t') 73 #endif 74 75 #ifndef FALSE 76 #define FALSE 0 77 #endif 78 79 80 /* 81 * Comparison values. These values are placed in the struct srch 82 * structure by buildsearchlist() and are used to compare values 83 * in matches(). 84 * EQUAL Attribute must equal this value 85 * NOTEQUAL Attribute must not equal this value 86 * EXISTS Attribute must exist 87 * NOEXISTS Attribute must not exist 88 * IGNORE Ignore this entry 89 * ENDLIST This entry ends the list 90 */ 91 92 #define EQUAL 1 93 #define NOTEQUAL 2 94 #define EXISTS 3 95 #define NOEXISTS 4 96 #define IGNORE 5 97 #define ENDLIST 0 98 99 100 /* 101 * Structure definitions: 102 * deviceent Defines a device that matches criteria 103 * srch Describes a criteria 104 */ 105 106 struct deviceent { 107 struct deviceent *next; /* Pointer to next item in the list */ 108 char *name; /* Presentation name of the device */ 109 }; 110 111 struct srch { 112 char *name; /* Name of field to compare */ 113 char *cmp; /* Value to compare against */ 114 int fcn; /* Type of comparison (see above) */ 115 }; 116 117 118 /* 119 * Local functions referenced 120 * oktoaddtolist() Determines if device can be added to the 121 * list by examining the devices list and 122 * the options governing the search 123 * initdevicelist() Initializes the linked list of devices 124 * to be included in the list-to-return 125 * freedevicelist() Frees the resources allocated to the linked 126 * list of devices 127 * addtodevicelist() Adds an entry to the linked list of devices 128 * buildsearchlist() Builds a list of struct srch structures from 129 * the criteria strings 130 * freesearchlist() Frees the resources allocated to the list of 131 * struct srch structures 132 * buildreturnlist() Builds the list of devices to return from the 133 * linked list of devices we've accumulated 134 * makealiaslist() Builds a list of aliases from the list of 135 * devices presented by the caller 136 * freealiaslist() Frees the resources allocated to the list of 137 * devices aliases 138 * getnextmatch() Get the next device that matches the search 139 * criteria 140 * matchallcriteria() See if the device attributes match all of the 141 * search criteria 142 * matchanycriteria() See if the device attributes match any of the 143 * search criteria 144 * matches() See if the criteria and attribute match 145 */ 146 147 static char *oktoaddtolist(char *, char **, char **, int); 148 static void initdevicelist(void); 149 static void freedevicelist(void); 150 static int addtodevicelist(char *); 151 static struct srch *buildsearchlist(char **); 152 static void freesearchlist(struct srch *); 153 static char **buildreturnlist(void); 154 static char **makealiaslist(char **); 155 static void freealiaslist(char **); 156 static char *getnextmatch(struct srch *, int); 157 static int matchallcriteria(struct devtabent *, struct srch *); 158 static int matchanycriteria(struct devtabent *, struct srch *); 159 static int matches(char *, char *, int); 160 161 162 /* 163 * Global Data 164 */ 165 166 /* 167 * Static Data 168 * devicelisthead The first item (dummy) in the linked list of devices 169 * we're building 170 * devicelist Structure describing the linked list of devices 171 */ 172 173 static struct deviceent devicelisthead; 174 static struct { 175 struct deviceent *head; 176 int count; 177 } devicelist = {&devicelisthead, 0}; 178 179 /* 180 * char **getdev(devices, criteria, options) 181 * char **devices 182 * char **criteria 183 * int options 184 * 185 * This function builds a list of devices that match criteria, 186 * governed by the device list. 187 * 188 * Arguments: 189 * devices The list of devices to select from or the list of 190 * devices to exclude, depending on the value of 191 * "options" 192 * criteria The list of criteria governing the device selection 193 * Of the form <attr><op><val> 194 * options Options controlling the device selection. May require 195 * that a device meet all of the criteria (default is 196 * any one of the criteria), or may require that the 197 * devices in the list of devices be excluded from the 198 * generated list (default is to select only those 199 * devices in the list) 200 * 201 * Returns: char ** 202 * The address of the first item in the list of devices that meet 203 * the selection criteria 204 */ 205 206 char ** 207 getdev( 208 char **devices, /* List of devices to constrain */ 209 char **criteria, /* List of selection criteria */ 210 int options) /* Options governing the search */ 211 { 212 /* Automatic data */ 213 char **aliases; /* List of constraining devices */ 214 char **returnlist; /* List of ptrs to aliases to return */ 215 struct srch *searchlist; /* Pointer to searching criteria */ 216 char *entry; /* Pointer to alias in record */ 217 int errflag; /* FLAG: TRUE if error */ 218 219 220 /* 221 * Initializations 222 */ 223 224 /* Make sure the exclude/include list is all aliases */ 225 aliases = makealiaslist(devices); 226 if (devices && !aliases) 227 return (NULL); 228 229 /* Build the search list */ 230 if (criteria) { 231 if (!(searchlist = buildsearchlist(criteria))) 232 return (NULL); 233 } else searchlist = NULL; 234 235 /* Initialize searching */ 236 initdevicelist(); 237 _setdevtab(); 238 239 240 /* 241 * Keep on going until we get no more matches 242 */ 243 244 errflag = FALSE; 245 while (!errflag && (entry = getnextmatch(searchlist, options))) { 246 if (entry = oktoaddtolist(entry, devices, aliases, options)) { 247 errflag = addtodevicelist(entry); 248 } 249 } 250 251 252 /* 253 * Clean up: 254 * - Free the entry space we've allocated. 255 * - Close the device table. 256 * - Build the list to return to the caller. 257 * - Free the accumulate device space (but not the strings!) 258 * - Free the alias list 259 * - Return the built list to the caller. 260 */ 261 262 returnlist = buildreturnlist(); 263 freedevicelist(); 264 freealiaslist(aliases); 265 _enddevtab(); 266 return (returnlist); 267 } 268 269 /* 270 * char *oktoaddtolist(devtabentry, devices, aliases, options) 271 * char *devtabentry 272 * char **devices 273 * char **aliases 274 * int options 275 * 276 * This function determines the device "devtabentry" can be 277 * added to the list of devices we're accumulating. If so, 278 * it returns the device name (not the alias). 279 * 280 * Arguments: 281 * devtabentry The device alias that may or may not belong in the 282 * list we're building. 283 * devices The devices specified by the caller 284 * aliases The aliases of the devices specified by the caller 285 * (1-1 correspondence with "devices") 286 * options Options controlling the search 287 */ 288 289 static char * 290 oktoaddtolist( 291 char *devtabentry, /* Alias to check against list */ 292 char **devices, /* List of devices to check against */ 293 char **aliases, /* List of alias of those devices */ 294 int options) /* Options governing search */ 295 { 296 /* Automatic data */ 297 char *rtnval; /* Value to return */ 298 int found; /* Flag: TRUE if found */ 299 300 /* If there's a constraint list, is this device in it? */ 301 if (devices && aliases) { 302 303 /* Set "found" to TRUE if the device is in the list */ 304 found = FALSE; 305 while (!found && *aliases) { 306 if (strcmp(devtabentry, *aliases) == 0) found = TRUE; 307 else { 308 devices++; 309 aliases++; 310 } 311 } 312 313 /* Set value to return */ 314 if (found) 315 rtnval = (options & DTAB_EXCLUDEFLAG) ? 316 NULL : *devices; 317 else 318 rtnval = (options & DTAB_EXCLUDEFLAG) ? 319 devtabentry : NULL; 320 321 } else rtnval = devtabentry; /* No constraint list */ 322 323 return (rtnval); 324 } 325 326 /* 327 * void initdevicelist() 328 * 329 * This function initializes the list of accumulated devices. 330 * 331 * Arguments: None 332 * 333 * Returns: Void. 334 * 335 * Notes: 336 */ 337 338 static void 339 initdevicelist(void) 340 { 341 /* Make the list a null list */ 342 (devicelist.head)->next = NULL; 343 devicelist.count = 0; 344 } 345 346 /* 347 * void freedevicelist() 348 * 349 * This function frees the resources allocated to the linked list of 350 * devices we've been accumulating. 351 * 352 * Arguments: none 353 * 354 * Returns: void 355 */ 356 357 static void 358 freedevicelist(void) 359 { 360 /* Automatic data */ 361 struct deviceent *pdevice; /* Pointer to current entry */ 362 char *freeblk; /* Pointer space to free */ 363 364 /* List has a dummy head node */ 365 pdevice = (devicelist.head)->next; 366 while (pdevice) { 367 freeblk = (char *) pdevice; 368 pdevice = pdevice->next; 369 free(freeblk); 370 } 371 } 372 373 /* 374 * int addtodevicelist(deventry) 375 * char *deventry 376 * 377 * This function adds the device <deventry> to the list of devices already 378 * accumulated. It will not add the device if that device already exists 379 * in the list. The function returns 0 if successful, -1 if not with 380 * "errno" set (by functions called) to indicate the error. 381 * 382 * Arguments: 383 * deventry char * 384 * The name of the device to add to the list of 385 * accumulated devices 386 * 387 * Returns: 388 * 0 If successful 389 * -1 If failed. "errno" will be set to a value that indicates the 390 * error. 391 * 392 * Notes: 393 * - The memory allocation scheme has the potential to fragment the memory 394 * in the malloc heap. We're allocating space for a local structure, 395 * which will be freed by getdev(), then allocating space for the device 396 * name, which will be freed (maybe) by the application using getdev(). 397 * Not worrying about this at the moment. 398 */ 399 400 static int 401 addtodevicelist(char *deventry) 402 { 403 /* Automatic data */ 404 struct deviceent *p; /* Pointer to current device */ 405 struct deviceent *q; /* Pointer to next device */ 406 struct deviceent *new; /* Pointer to the alloc'd new node */ 407 char *str; /* Pointer to alloc'd space for name */ 408 int rtncd; /* Value to return to the caller */ 409 int cmpcd; /* strcmp() value, comparing names */ 410 int done; /* Loop control, TRUE if done */ 411 412 413 /* Initializations */ 414 rtncd = FALSE; 415 416 417 /* 418 * Find the place in the found device list devicelist where this 419 * device is to reside 420 */ 421 422 p = devicelist.head; 423 done = FALSE; 424 while (!done) { 425 q = p->next; 426 if (!q) done = TRUE; 427 else if ((cmpcd = strcmp(deventry, q->name)) <= 0) done = TRUE; 428 else p = q; 429 } 430 431 /* 432 * If the device is not already in the list, insert it in the list 433 */ 434 435 if (!q || (cmpcd != 0)) { 436 437 /* Alloc space for the new node */ 438 if (new = malloc(sizeof (struct deviceent))) { 439 440 /* Alloc space for the device character string */ 441 if (str = malloc(strlen(deventry)+1)) { 442 443 /* 444 * Insert an entry in the found device list containing 445 * this device name 446 */ 447 new->next = q; 448 p->next = new; 449 new->name = strcpy(str, deventry); 450 devicelist.count++; 451 } 452 453 /* Couldn't alloc space for the device name. Error. */ 454 else rtncd = TRUE; 455 } 456 457 /* Couldn't alloc space for new node in the found list. Error. */ 458 else rtncd = TRUE; 459 460 } 461 462 /* Return an value indicating success or failure */ 463 return (rtncd); 464 } 465 466 /* 467 * struct srch *buildsearchlist(criteria) 468 * char **criteria 469 * 470 * This function builds a list of search criteria structures from the 471 * criteria strings in the list of criteria whose first argument is 472 * specified by "criteria". 473 * 474 * Arguments: 475 * criteria The address of the first item in a list of 476 * character-strings specifying search criteria 477 * 478 * Returns: struct srch * 479 * The address of the structure in the list of structures describing the 480 * search criteria. 481 * 482 * Notes: 483 * - The only "regular expression" currently supported by the 484 * kywd:exp and kywd!:exp forms is exp=*. This function assumes 485 * that kywd:exp means "if kywd exist" and that kywd!:exp means 486 * "if kywd doesn't exist". 487 */ 488 489 static struct srch * 490 buildsearchlist(char **criteria) /* Criteria from caller */ 491 { 492 /* Automatic data */ 493 struct srch *rtnbuf; /* Value to return */ 494 struct srch *psrch; /* Running pointer */ 495 char *str; /* Ptr to malloc()ed string space */ 496 char *p; /* Temp pointer to char */ 497 int noerror; /* TRUE if all's well */ 498 int n; /* Temp counter */ 499 char **pp; /* Running ptr to (char *) */ 500 501 502 /* Initializations */ 503 rtnbuf = NULL; /* Nothing to return yet */ 504 noerror = TRUE; /* No errors (yet) */ 505 506 /* If we were given any criteria ... */ 507 if (criteria) { 508 509 /* Count the number of criteria in the list */ 510 for (n = 1, pp = criteria; *pp++; n++) 511 ; 512 513 /* Allocate space for structures describing the criteria */ 514 if (rtnbuf = malloc(n*sizeof (struct srch))) { 515 516 /* Build structures describing the criteria */ 517 pp = criteria; 518 psrch = rtnbuf; 519 while (noerror && *pp) { 520 521 /* Keep list sane for cleanup if necessary */ 522 psrch->fcn = ENDLIST; 523 524 /* Alloc space for strings referenced by the structure */ 525 if (str = malloc(strlen(*pp)+1)) { 526 527 /* Extract field name, function, and compare string */ 528 (void) strcpy(str, *pp); 529 530 /* If criteria contains an equal sign ('=') ... */ 531 if (p = strchr(str+1, '=')) { 532 if (*(p-1) == '!') { 533 *(p-1) = '\0'; 534 psrch->fcn = NOTEQUAL; 535 } else { 536 *p = '\0'; 537 psrch->fcn = EQUAL; 538 } 539 psrch->cmp = p+1; 540 psrch->name = str; 541 psrch++; 542 } 543 544 /* If criteria contains a colon (':') ... */ 545 else if (p = strchr(str+1, ':')) { 546 if (*(p-1) == '!') { 547 *(p-1) = '\0'; 548 psrch->fcn = NOEXISTS; 549 } else { 550 *p = '\0'; 551 psrch->fcn = EXISTS; 552 } 553 psrch->cmp = p+1; 554 psrch->name = str; 555 psrch++; 556 } 557 } else { 558 /* Unable to malloc() string space. Clean up */ 559 freesearchlist(rtnbuf); 560 noerror = FALSE; 561 } 562 /* Next criteria */ 563 pp++; 564 } 565 /* Terminate list */ 566 if (noerror) psrch->fcn = ENDLIST; 567 } 568 } 569 570 /* Return a pointer to allocated space (if any) */ 571 return (rtnbuf); 572 } 573 574 /* 575 * void freesearchlist(list) 576 * struct srch *list 577 * 578 * This function frees the resources allocated to the searchlist <list>. 579 * 580 * Arguments: 581 * list The list whose resources are to be released. 582 * 583 * Returns: void 584 */ 585 586 static void 587 freesearchlist(struct srch *list) 588 { 589 /* Automatic data */ 590 struct srch *psrch; /* Running ptr to structs */ 591 592 593 /* Free all of the string space allocated for the structure elememts */ 594 for (psrch = list; psrch->fcn != ENDLIST; psrch++) { 595 free(psrch->name); 596 } 597 598 /* Free the list space */ 599 free(list); 600 } 601 602 /* 603 * char **buildreturnlist() 604 * 605 * This function builds a list of addresses of character-strings 606 * to be returned from the linked-list of devices we've been 607 * building. It returns a pointer to the first item in that list. 608 * 609 * Arguments: none 610 * 611 * Returns: char ** 612 * The address of the first item in the return list 613 */ 614 615 static char ** 616 buildreturnlist(void) 617 { 618 /* Automatic data */ 619 char **list; 620 char **q; 621 struct deviceent *p; 622 623 624 /* 625 * Allocate space for the return list, 626 * with space for the terminating node 627 */ 628 629 if (list = malloc((devicelist.count+1)*sizeof (char *))) { 630 631 /* 632 * Walk the list of accumulated devices, putting pointers to 633 * device names in the list to return 634 */ 635 636 q = list; 637 for (p = devicelist.head->next; p; p = p->next) *q++ = p->name; 638 639 /* End the list with a null-pointer */ 640 *q = NULL; 641 } 642 643 644 /* Return a pointer to the list we've built */ 645 return (list); 646 } 647 648 /* 649 * char **makealiaslist(devices) 650 * char **devices List of aliases 651 * 652 * Builds a list of aliases of the devices in the "devices" 653 * list. This list will be terminated by (char *) NULL and 654 * will have the same number of elements as "devices". If 655 * a device couldn't be found, that alias will be "". There 656 * will be a one-to-one correspondence of devices to aliases 657 * in the device list "devices" and the generated list. 658 * 659 * Arguments: 660 * devices The list of devices to derive aliases from 661 * 662 * Returns: char ** 663 * The address of the list of addresses of aliases. The list 664 * and aliases will be allocated using the malloc() function. 665 */ 666 667 static char ** 668 makealiaslist(char **devices) 669 { 670 /* Automatic data */ 671 char **pp; /* Running ptr to (char *) */ 672 char **qq; /* Running ptr to (char *) */ 673 char **aliases; /* List being returned */ 674 char *alias; /* Alias of current device */ 675 int olderrno; /* Value of errno on entry */ 676 int noerror; /* Flag, TRUE if all's well */ 677 int n; /* Count of entries in "devices" */ 678 679 680 noerror = TRUE; 681 olderrno = errno; 682 if (devices) { 683 684 /* Get the number of entries in the constaint list */ 685 for (n = 1, pp = devices; *pp; pp++) n++; 686 687 /* Get space for the alias list */ 688 if (aliases = malloc(n*sizeof (char *))) { 689 690 /* Build the alias list */ 691 qq = aliases; 692 for (pp = devices; noerror && *pp; pp++) { 693 694 /* Get the device's alias and put it in the list */ 695 if (alias = devattr(*pp, DTAB_ALIAS)) *qq++ = alias; 696 else { 697 errno = olderrno; 698 if (alias = malloc(strlen("")+1)) 699 *qq++ = strcpy(alias, ""); 700 else { 701 /* No space for a null string? Yeech... */ 702 for (qq = aliases; *qq; qq++) free(*qq); 703 free(aliases); 704 aliases = NULL; 705 noerror = FALSE; 706 } 707 } 708 } 709 if (noerror) 710 *qq = NULL; 711 712 } 713 714 } else 715 aliases = NULL; /* No constraint list */ 716 717 /* Return ptr to generated list or NULL if none or error */ 718 return (aliases); 719 } 720 721 /* 722 * void freealiaslist(aliaslist) 723 * char **aliaslist; 724 * 725 * Free the space allocated to the aliaslist. It frees the space 726 * allocated to the character-strings referenced by the list then 727 * it frees the list. 728 * 729 * Arguments: 730 * aliaslist The address of the first item in the list of 731 * aliases that is to be freed 732 * 733 * Returns: void 734 */ 735 736 static void 737 freealiaslist(char **aliaslist) /* Ptr to new device list */ 738 { 739 /* Automatic Data */ 740 char **pp; /* Running pointer */ 741 742 /* If there's a list ... */ 743 if (aliaslist) { 744 745 /* For each entry in the old list, free the entry */ 746 for (pp = aliaslist; *pp; pp++) free(*pp); 747 748 /* Free the list */ 749 free(aliaslist); 750 } 751 } 752 753 /* 754 * char *getnextmatch(criteria, options) 755 * struct srch *criteria 756 * int options 757 * 758 * Gets the next device in the device table that matches the criteria. 759 * Returns the alias of that device. 760 * 761 * Arguments: 762 * criteria The linked list of criteria to use to match a device 763 * options Options modifying the criteria (only one that's really 764 * important is the DTAB_ANDCRITERIA flag) 765 * 766 * Returns: char * 767 * A pointer to a malloc()ed string containing the alias of the next 768 * device that matches the criteria, or (char *) NULL if none. 769 */ 770 771 static char * 772 getnextmatch(struct srch *criteria, int options) 773 { 774 /* Automatic data */ 775 struct devtabent *devtabent; /* Ptr to current record */ 776 char *alias; /* Alias of device found */ 777 int notdone; /* Flag, done yet? */ 778 int noerror; /* Flag, had an error yet? */ 779 780 781 /* 782 * Initializations: 783 * - No alias yet 784 * - Not finished yet 785 * - Make sure there are criteria we're to use 786 */ 787 788 alias = NULL; 789 notdone = TRUE; 790 noerror = TRUE; 791 792 /* If we're to "and" the criteria... */ 793 if (options & DTAB_ANDCRITERIA) { 794 795 /* 796 * Search the device table until we've got a record that matches 797 * all of the criteria or we run out of records 798 */ 799 800 while (notdone && (devtabent = _getdevtabent())) { 801 if (!devtabent->comment) { 802 if (!criteria || matchallcriteria(devtabent, criteria)) { 803 if (alias = malloc(strlen(devtabent->alias)+1)) 804 (void) strcpy(alias, devtabent->alias); 805 else noerror = FALSE; 806 notdone = FALSE; 807 } 808 } 809 _freedevtabent(devtabent); 810 } 811 } else { 812 813 /* 814 * Search the device table until we've got a record that matches 815 * any of the criteria or we run out of records 816 */ 817 818 while (notdone && (devtabent = _getdevtabent())) { 819 if (!devtabent->comment) { 820 if (!criteria || matchanycriteria(devtabent, criteria)) { 821 if (alias = malloc(strlen(devtabent->alias)+1)) 822 (void) strcpy(alias, devtabent->alias); 823 else noerror = FALSE; 824 notdone = FALSE; 825 } 826 } 827 _freedevtabent(devtabent); 828 } 829 } 830 831 832 /* Return pointer to extracted alias (or NULL if none) */ 833 if ((alias == NULL) && noerror) errno = ENOENT; 834 return (alias); 835 } 836 837 /* 838 * int matchallcriteria(devtabent, criteria) 839 * 840 * This function examines the record contained in "devtabent" and 841 * determines if that record meets all of the criteria specified by 842 * "criteria". 843 * 844 * Arguments: 845 * struct devtabent *devtabent The device table entry to examine. 846 * struct srch *criteria The criteria to match. 847 * 848 * Returns: int 849 * Returns TRUE if the record matches criteria, FALSE otherwise. 850 */ 851 852 static int 853 matchallcriteria( 854 struct devtabent *ent, /* Entry to check */ 855 struct srch *criteria) /* Criteria governing match */ 856 { 857 /* Automatic data */ 858 struct srch *p; /* Pointer to current criteria */ 859 struct attrval *q; /* Pointer to current attr/val pair */ 860 int notfound; /* TRUE if attr found in list */ 861 int failed; /* TRUE if record failed to match */ 862 863 864 /* Test only if there's criteria to test against */ 865 if (criteria && (criteria->fcn != ENDLIST)) { 866 867 failed = FALSE; 868 for (p = criteria; !failed && (p->fcn != ENDLIST); p++) { 869 870 /* 871 * Don't compare against this criteria if it's function is 872 * "IGNORE" 873 */ 874 if (p->fcn != IGNORE) { 875 if (p->fcn != NOEXISTS) { 876 877 /* Alias? */ 878 if (strcmp(p->name, DTAB_ALIAS) == 0) 879 failed = !matches(ent->alias, p->cmp, p->fcn); 880 881 /* Char special device? */ 882 else if (strcmp(p->name, DTAB_CDEVICE) == 0) 883 failed = !matches(ent->cdevice, p->cmp, p->fcn); 884 885 /* Block special device? */ 886 else if (strcmp(p->name, DTAB_BDEVICE) == 0) 887 failed = !matches(ent->bdevice, p->cmp, p->fcn); 888 889 /* Pathname? */ 890 else if (strcmp(p->name, DTAB_PATHNAME) == 0) 891 failed = !matches(ent->pathname, p->cmp, p->fcn); 892 893 /* Check other attributes... */ 894 else { 895 notfound = TRUE; 896 q = ent->attrlist; 897 while (notfound && q) { 898 if (strcmp(p->name, q->attr) == 0) { 899 notfound = FALSE; 900 if (!matches(q->val, p->cmp, p->fcn)) 901 failed = TRUE; 902 } else q = q->next; 903 } 904 if (notfound) failed = TRUE; 905 } 906 } else { 907 if (strcmp(p->name, DTAB_ALIAS) == 0) failed = TRUE; 908 else if (strcmp(p->name, DTAB_CDEVICE) == 0) 909 failed = FALSE; 910 else if (strcmp(p->name, DTAB_BDEVICE) == 0) 911 failed = FALSE; 912 else if (strcmp(p->name, DTAB_PATHNAME) == 0) 913 failed = FALSE; 914 else { 915 q = ent->attrlist; 916 while (!failed && q) { 917 if (strcmp(p->name, q->attr) == 0) 918 failed = TRUE; 919 else q = q->next; 920 } 921 } 922 } 923 924 } /* Search function is not "IGNORE" */ 925 926 } /* for loop, checking each criteria */ 927 928 } /* if (criteria) */ 929 930 else failed = FALSE; /* No criteria specified, it's a match */ 931 932 933 /* Return a value indicating if the record matches all criteria */ 934 return (!failed); 935 } 936 937 /* 938 * int matchanycriteria(devtabent, criteria) 939 * 940 * This function examines the record contained in "devtabent" and 941 * determines if that record meets any of the criteria specified by 942 * "criteria". 943 * 944 * Arguments: 945 * struct devtabent *devtabent The device table entry to examine. 946 * struct srch *criteria The criteria to match. 947 * 948 * Returns: int 949 * Returns TRUE if the record matches criteria, FALSE otherwise. 950 */ 951 952 static int 953 matchanycriteria( 954 struct devtabent *ent, /* Entry to check */ 955 struct srch *criteria) /* Criteria governing match */ 956 { 957 /* Automatic data */ 958 struct srch *p; /* Pointer to current criteria */ 959 struct attrval *q; /* Pointer to current attr/val pair */ 960 int matched; /* FLAG: TRUE if record matched */ 961 int found; /* FLAG: TRUE if attribute found */ 962 963 964 /* Test only if there's criteria to test against */ 965 if (criteria && (criteria->fcn != ENDLIST)) { 966 967 matched = FALSE; 968 for (p = criteria; !matched && (p->fcn != ENDLIST); p++) { 969 970 /* 971 * Don't compare against this criteria if it's function is 972 * "IGNORE" 973 */ 974 if (p->fcn != IGNORE) { 975 if (p->fcn != NOEXISTS) { 976 977 /* Alias? */ 978 if (strcmp(p->name, DTAB_ALIAS) == 0) 979 matched = matches(ent->alias, p->cmp, p->fcn); 980 981 /* Char special device? */ 982 else if (strcmp(p->name, DTAB_CDEVICE) == 0) 983 matched = matches(ent->cdevice, p->cmp, p->fcn); 984 985 /* Block special device? */ 986 else if (strcmp(p->name, DTAB_BDEVICE) == 0) 987 matched = matches(ent->bdevice, p->cmp, p->fcn); 988 989 /* Pathname? */ 990 else if (strcmp(p->name, DTAB_PATHNAME) == 0) 991 matched = matches(ent->pathname, p->cmp, p->fcn); 992 993 /* Check other attributes... */ 994 else { 995 q = ent->attrlist; 996 found = FALSE; 997 while (!found && q) 998 if (strcmp(p->name, q->attr) == 0) { 999 matched = matches(q->val, p->cmp, p->fcn); 1000 found = TRUE; 1001 } else q = q->next; 1002 } 1003 } else { 1004 if (strcmp(p->name, DTAB_ALIAS) == 0) matched = FALSE; 1005 else if (strcmp(p->name, DTAB_CDEVICE) == 0) 1006 matched = FALSE; 1007 else if (strcmp(p->name, DTAB_BDEVICE) == 0) 1008 matched = FALSE; 1009 else if (strcmp(p->name, DTAB_PATHNAME) == 0) 1010 matched = FALSE; 1011 else { 1012 q = ent->attrlist; 1013 matched = TRUE; 1014 while (matched && q) { 1015 if (strcmp(p->name, q->attr) == 0) 1016 matched = FALSE; 1017 else q = q->next; 1018 } 1019 } 1020 } 1021 } /* Search function is not "IGNORE" */ 1022 1023 } /* for loop, checking each criteria */ 1024 1025 } /* if (criteria) */ 1026 1027 else matched = TRUE; /* No criteria specified, it's a match */ 1028 1029 1030 /* Return a value indicating if the record matches all criteria */ 1031 return (matched); 1032 } 1033 1034 /* 1035 * int matches(value, compare, function) 1036 * char *value 1037 * char *compare 1038 * int function 1039 * 1040 * This function sees if the operation <function> is satisfied by 1041 * comparing the value <value> with <compare>. It returns TRUE 1042 * if so, FALSE otherwise. 1043 * 1044 * Arguments: 1045 * value Value to compare 1046 * compare Value to compare against 1047 * function Function to be satisfied 1048 * 1049 * Returns: int 1050 * TRUE if the function is satisfied, FALSE otherwise 1051 */ 1052 1053 static int 1054 matches(char *value, char *compare, int function) 1055 { 1056 /* Automatic data */ 1057 int rtn; /* Value to return */ 1058 1059 1060 if (value == NULL) 1061 value = ""; 1062 1063 /* Do case depending on the function */ 1064 switch (function) { 1065 1066 /* attr=val */ 1067 case EQUAL: 1068 rtn = (strcmp(value, compare) == 0); 1069 break; 1070 1071 /* attr!=val */ 1072 case NOTEQUAL: 1073 rtn = (strcmp(value, compare) != 0); 1074 break; 1075 1076 /* attr:* */ 1077 case EXISTS: 1078 rtn = TRUE; 1079 break; 1080 1081 /* attr!:* */ 1082 case NOEXISTS: 1083 rtn = FALSE; 1084 break; 1085 1086 /* Shouldn't get here... */ 1087 default: 1088 rtn = FALSE; 1089 break; 1090 } 1091 1092 /* Return a value indicating if the match was made */ 1093 return (rtn); 1094 } 1095