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