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 **
getdev(char ** devices,char ** criteria,int options)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 *
oktoaddtolist(char * devtabentry,char ** devices,char ** aliases,int options)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
initdevicelist(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
freedevicelist(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
addtodevicelist(char * deventry)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 *
buildsearchlist(char ** criteria)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
freesearchlist(struct srch * list)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 **
buildreturnlist(void)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 **
makealiaslist(char ** devices)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
freealiaslist(char ** aliaslist)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 *
getnextmatch(struct srch * criteria,int options)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
matchallcriteria(struct devtabent * ent,struct srch * criteria)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
matchanycriteria(struct devtabent * ent,struct srch * criteria)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
matches(char * value,char * compare,int function)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