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