summaryrefslogtreecommitdiff
path: root/usr/src/lib/libadm/common/getdev.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libadm/common/getdev.c')
-rw-r--r--usr/src/lib/libadm/common/getdev.c1095
1 files changed, 1095 insertions, 0 deletions
diff --git a/usr/src/lib/libadm/common/getdev.c b/usr/src/lib/libadm/common/getdev.c
new file mode 100644
index 0000000000..8e4401140f
--- /dev/null
+++ b/usr/src/lib/libadm/common/getdev.c
@@ -0,0 +1,1095 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License"). You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
+
+/*
+ * Copyright (c) 1997, by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.4 */
+/*LINTLIBRARY*/
+
+/*
+ * getdev.c
+ *
+ * Contents:
+ * getdev() List devices that match certain criteria.
+ */
+
+/*
+ * Header files referenced:
+ * <sys/types.h> System Data Types
+ * <errno.h> Error handling
+ * <fcntl.h> File controlling
+ * <ctype.h> Character types
+ * <string.h> String handling
+ * <devmgmt.h> Global device-management def'ns
+ * "devtab.h" Local device-management dev'ns
+ */
+
+#include <sys/types.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <string.h>
+#include <devmgmt.h>
+#include "devtab.h"
+#include <stdlib.h>
+
+/*
+ * Local definitions
+ * NULL Nil address
+ * TRUE Boolean TRUE
+ * FALSE Boolean FALSE
+ */
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef TRUE
+#define TRUE ('t')
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+
+/*
+ * Comparison values. These values are placed in the struct srch
+ * structure by buildsearchlist() and are used to compare values
+ * in matches().
+ * EQUAL Attribute must equal this value
+ * NOTEQUAL Attribute must not equal this value
+ * EXISTS Attribute must exist
+ * NOEXISTS Attribute must not exist
+ * IGNORE Ignore this entry
+ * ENDLIST This entry ends the list
+ */
+
+#define EQUAL 1
+#define NOTEQUAL 2
+#define EXISTS 3
+#define NOEXISTS 4
+#define IGNORE 5
+#define ENDLIST 0
+
+
+/*
+ * Structure definitions:
+ * deviceent Defines a device that matches criteria
+ * srch Describes a criteria
+ */
+
+struct deviceent {
+ struct deviceent *next; /* Pointer to next item in the list */
+ char *name; /* Presentation name of the device */
+};
+
+struct srch {
+ char *name; /* Name of field to compare */
+ char *cmp; /* Value to compare against */
+ int fcn; /* Type of comparison (see above) */
+};
+
+
+/*
+ * Local functions referenced
+ * oktoaddtolist() Determines if device can be added to the
+ * list by examining the devices list and
+ * the options governing the search
+ * initdevicelist() Initializes the linked list of devices
+ * to be included in the list-to-return
+ * freedevicelist() Frees the resources allocated to the linked
+ * list of devices
+ * addtodevicelist() Adds an entry to the linked list of devices
+ * buildsearchlist() Builds a list of struct srch structures from
+ * the criteria strings
+ * freesearchlist() Frees the resources allocated to the list of
+ * struct srch structures
+ * buildreturnlist() Builds the list of devices to return from the
+ * linked list of devices we've accumulated
+ * makealiaslist() Builds a list of aliases from the list of
+ * devices presented by the caller
+ * freealiaslist() Frees the resources allocated to the list of
+ * devices aliases
+ * getnextmatch() Get the next device that matches the search
+ * criteria
+ * matchallcriteria() See if the device attributes match all of the
+ * search criteria
+ * matchanycriteria() See if the device attributes match any of the
+ * search criteria
+ * matches() See if the criteria and attribute match
+ */
+
+static char *oktoaddtolist(char *, char **, char **, int);
+static void initdevicelist(void);
+static void freedevicelist(void);
+static int addtodevicelist(char *);
+static struct srch *buildsearchlist(char **);
+static void freesearchlist(struct srch *);
+static char **buildreturnlist(void);
+static char **makealiaslist(char **);
+static void freealiaslist(char **);
+static char *getnextmatch(struct srch *, int);
+static int matchallcriteria(struct devtabent *, struct srch *);
+static int matchanycriteria(struct devtabent *, struct srch *);
+static int matches(char *, char *, int);
+
+
+/*
+ * Global Data
+ */
+
+/*
+ * Static Data
+ * devicelisthead The first item (dummy) in the linked list of devices
+ * we're building
+ * devicelist Structure describing the linked list of devices
+ */
+
+static struct deviceent devicelisthead;
+static struct {
+ struct deviceent *head;
+ int count;
+} devicelist = {&devicelisthead, 0};
+
+/*
+ * char **getdev(devices, criteria, options)
+ * char **devices
+ * char **criteria
+ * int options
+ *
+ * This function builds a list of devices that match criteria,
+ * governed by the device list.
+ *
+ * Arguments:
+ * devices The list of devices to select from or the list of
+ * devices to exclude, depending on the value of
+ * "options"
+ * criteria The list of criteria governing the device selection
+ * Of the form <attr><op><val>
+ * options Options controlling the device selection. May require
+ * that a device meet all of the criteria (default is
+ * any one of the criteria), or may require that the
+ * devices in the list of devices be excluded from the
+ * generated list (default is to select only those
+ * devices in the list)
+ *
+ * Returns: char **
+ * The address of the first item in the list of devices that meet
+ * the selection criteria
+ */
+
+char **
+getdev(
+ char **devices, /* List of devices to constrain */
+ char **criteria, /* List of selection criteria */
+ int options) /* Options governing the search */
+{
+ /* Automatic data */
+ char **aliases; /* List of constraining devices */
+ char **returnlist; /* List of ptrs to aliases to return */
+ struct srch *searchlist; /* Pointer to searching criteria */
+ char *entry; /* Pointer to alias in record */
+ int errflag; /* FLAG: TRUE if error */
+
+
+ /*
+ * Initializations
+ */
+
+ /* Make sure the exclude/include list is all aliases */
+ aliases = makealiaslist(devices);
+ if (devices && !aliases)
+ return (NULL);
+
+ /* Build the search list */
+ if (criteria) {
+ if (!(searchlist = buildsearchlist(criteria)))
+ return (NULL);
+ } else searchlist = NULL;
+
+ /* Initialize searching */
+ initdevicelist();
+ _setdevtab();
+
+
+ /*
+ * Keep on going until we get no more matches
+ */
+
+ errflag = FALSE;
+ while (!errflag && (entry = getnextmatch(searchlist, options))) {
+ if (entry = oktoaddtolist(entry, devices, aliases, options)) {
+ errflag = addtodevicelist(entry);
+ }
+ }
+
+
+ /*
+ * Clean up:
+ * - Free the entry space we've allocated.
+ * - Close the device table.
+ * - Build the list to return to the caller.
+ * - Free the accumulate device space (but not the strings!)
+ * - Free the alias list
+ * - Return the built list to the caller.
+ */
+
+ returnlist = buildreturnlist();
+ freedevicelist();
+ freealiaslist(aliases);
+ _enddevtab();
+ return (returnlist);
+}
+
+/*
+ * char *oktoaddtolist(devtabentry, devices, aliases, options)
+ * char *devtabentry
+ * char **devices
+ * char **aliases
+ * int options
+ *
+ * This function determines the device "devtabentry" can be
+ * added to the list of devices we're accumulating. If so,
+ * it returns the device name (not the alias).
+ *
+ * Arguments:
+ * devtabentry The device alias that may or may not belong in the
+ * list we're building.
+ * devices The devices specified by the caller
+ * aliases The aliases of the devices specified by the caller
+ * (1-1 correspondence with "devices")
+ * options Options controlling the search
+ */
+
+static char *
+oktoaddtolist(
+ char *devtabentry, /* Alias to check against list */
+ char **devices, /* List of devices to check against */
+ char **aliases, /* List of alias of those devices */
+ int options) /* Options governing search */
+{
+ /* Automatic data */
+ char *rtnval; /* Value to return */
+ int found; /* Flag: TRUE if found */
+
+ /* If there's a constraint list, is this device in it? */
+ if (devices && aliases) {
+
+ /* Set "found" to TRUE if the device is in the list */
+ found = FALSE;
+ while (!found && *aliases) {
+ if (strcmp(devtabentry, *aliases) == 0) found = TRUE;
+ else {
+ devices++;
+ aliases++;
+ }
+ }
+
+ /* Set value to return */
+ if (found)
+ rtnval = (options & DTAB_EXCLUDEFLAG) ?
+ NULL : *devices;
+ else
+ rtnval = (options & DTAB_EXCLUDEFLAG) ?
+ devtabentry : NULL;
+
+ } else rtnval = devtabentry; /* No constraint list */
+
+ return (rtnval);
+}
+
+/*
+ * void initdevicelist()
+ *
+ * This function initializes the list of accumulated devices.
+ *
+ * Arguments: None
+ *
+ * Returns: Void.
+ *
+ * Notes:
+ */
+
+static void
+initdevicelist(void)
+{
+ /* Make the list a null list */
+ (devicelist.head)->next = NULL;
+ devicelist.count = 0;
+}
+
+/*
+ * void freedevicelist()
+ *
+ * This function frees the resources allocated to the linked list of
+ * devices we've been accumulating.
+ *
+ * Arguments: none
+ *
+ * Returns: void
+ */
+
+static void
+freedevicelist(void)
+{
+ /* Automatic data */
+ struct deviceent *pdevice; /* Pointer to current entry */
+ char *freeblk; /* Pointer space to free */
+
+ /* List has a dummy head node */
+ pdevice = (devicelist.head)->next;
+ while (pdevice) {
+ freeblk = (char *) pdevice;
+ pdevice = pdevice->next;
+ free(freeblk);
+ }
+}
+
+/*
+ * int addtodevicelist(deventry)
+ * char *deventry
+ *
+ * This function adds the device <deventry> to the list of devices already
+ * accumulated. It will not add the device if that device already exists
+ * in the list. The function returns 0 if successful, -1 if not with
+ * "errno" set (by functions called) to indicate the error.
+ *
+ * Arguments:
+ * deventry char *
+ * The name of the device to add to the list of
+ * accumulated devices
+ *
+ * Returns:
+ * 0 If successful
+ * -1 If failed. "errno" will be set to a value that indicates the
+ * error.
+ *
+ * Notes:
+ * - The memory allocation scheme has the potential to fragment the memory
+ * in the malloc heap. We're allocating space for a local structure,
+ * which will be freed by getdev(), then allocating space for the device
+ * name, which will be freed (maybe) by the application using getdev().
+ * Not worrying about this at the moment.
+ */
+
+static int
+addtodevicelist(char *deventry)
+{
+ /* Automatic data */
+ struct deviceent *p; /* Pointer to current device */
+ struct deviceent *q; /* Pointer to next device */
+ struct deviceent *new; /* Pointer to the alloc'd new node */
+ char *str; /* Pointer to alloc'd space for name */
+ int rtncd; /* Value to return to the caller */
+ int cmpcd; /* strcmp() value, comparing names */
+ int done; /* Loop control, TRUE if done */
+
+
+ /* Initializations */
+ rtncd = FALSE;
+
+
+ /*
+ * Find the place in the found device list devicelist where this
+ * device is to reside
+ */
+
+ p = devicelist.head;
+ done = FALSE;
+ while (!done) {
+ q = p->next;
+ if (!q) done = TRUE;
+ else if ((cmpcd = strcmp(deventry, q->name)) <= 0) done = TRUE;
+ else p = q;
+ }
+
+ /*
+ * If the device is not already in the list, insert it in the list
+ */
+
+ if (!q || (cmpcd != 0)) {
+
+ /* Alloc space for the new node */
+ if (new = malloc(sizeof (struct deviceent))) {
+
+ /* Alloc space for the device character string */
+ if (str = malloc(strlen(deventry)+1)) {
+
+ /*
+ * Insert an entry in the found device list containing
+ * this device name
+ */
+ new->next = q;
+ p->next = new;
+ new->name = strcpy(str, deventry);
+ devicelist.count++;
+ }
+
+ /* Couldn't alloc space for the device name. Error. */
+ else rtncd = TRUE;
+ }
+
+ /* Couldn't alloc space for new node in the found list. Error. */
+ else rtncd = TRUE;
+
+ }
+
+ /* Return an value indicating success or failure */
+ return (rtncd);
+}
+
+/*
+ * struct srch *buildsearchlist(criteria)
+ * char **criteria
+ *
+ * This function builds a list of search criteria structures from the
+ * criteria strings in the list of criteria whose first argument is
+ * specified by "criteria".
+ *
+ * Arguments:
+ * criteria The address of the first item in a list of
+ * character-strings specifying search criteria
+ *
+ * Returns: struct srch *
+ * The address of the structure in the list of structures describing the
+ * search criteria.
+ *
+ * Notes:
+ * - The only "regular expression" currently supported by the
+ * kywd:exp and kywd!:exp forms is exp=*. This function assumes
+ * that kywd:exp means "if kywd exist" and that kywd!:exp means
+ * "if kywd doesn't exist".
+ */
+
+static struct srch *
+buildsearchlist(char **criteria) /* Criteria from caller */
+{
+ /* Automatic data */
+ struct srch *rtnbuf; /* Value to return */
+ struct srch *psrch; /* Running pointer */
+ char *str; /* Ptr to malloc()ed string space */
+ char *p; /* Temp pointer to char */
+ int noerror; /* TRUE if all's well */
+ int n; /* Temp counter */
+ char **pp; /* Running ptr to (char *) */
+
+
+ /* Initializations */
+ rtnbuf = NULL; /* Nothing to return yet */
+ noerror = TRUE; /* No errors (yet) */
+
+ /* If we were given any criteria ... */
+ if (criteria) {
+
+ /* Count the number of criteria in the list */
+ for (n = 1, pp = criteria; *pp++; n++)
+ ;
+
+ /* Allocate space for structures describing the criteria */
+ if (rtnbuf = malloc(n*sizeof (struct srch))) {
+
+ /* Build structures describing the criteria */
+ pp = criteria;
+ psrch = rtnbuf;
+ while (noerror && *pp) {
+
+ /* Keep list sane for cleanup if necessary */
+ psrch->fcn = ENDLIST;
+
+ /* Alloc space for strings referenced by the structure */
+ if (str = malloc(strlen(*pp)+1)) {
+
+ /* Extract field name, function, and compare string */
+ (void) strcpy(str, *pp);
+
+ /* If criteria contains an equal sign ('=') ... */
+ if (p = strchr(str+1, '=')) {
+ if (*(p-1) == '!') {
+ *(p-1) = '\0';
+ psrch->fcn = NOTEQUAL;
+ } else {
+ *p = '\0';
+ psrch->fcn = EQUAL;
+ }
+ psrch->cmp = p+1;
+ psrch->name = str;
+ psrch++;
+ }
+
+ /* If criteria contains a colon (':') ... */
+ else if (p = strchr(str+1, ':')) {
+ if (*(p-1) == '!') {
+ *(p-1) = '\0';
+ psrch->fcn = NOEXISTS;
+ } else {
+ *p = '\0';
+ psrch->fcn = EXISTS;
+ }
+ psrch->cmp = p+1;
+ psrch->name = str;
+ psrch++;
+ }
+ } else {
+ /* Unable to malloc() string space. Clean up */
+ freesearchlist(rtnbuf);
+ noerror = FALSE;
+ }
+ /* Next criteria */
+ pp++;
+ }
+ /* Terminate list */
+ if (noerror) psrch->fcn = ENDLIST;
+ }
+ }
+
+ /* Return a pointer to allocated space (if any) */
+ return (rtnbuf);
+}
+
+/*
+ * void freesearchlist(list)
+ * struct srch *list
+ *
+ * This function frees the resources allocated to the searchlist <list>.
+ *
+ * Arguments:
+ * list The list whose resources are to be released.
+ *
+ * Returns: void
+ */
+
+static void
+freesearchlist(struct srch *list)
+{
+ /* Automatic data */
+ struct srch *psrch; /* Running ptr to structs */
+
+
+ /* Free all of the string space allocated for the structure elememts */
+ for (psrch = list; psrch->fcn != ENDLIST; psrch++) {
+ free(psrch->name);
+ }
+
+ /* Free the list space */
+ free(list);
+}
+
+/*
+ * char **buildreturnlist()
+ *
+ * This function builds a list of addresses of character-strings
+ * to be returned from the linked-list of devices we've been
+ * building. It returns a pointer to the first item in that list.
+ *
+ * Arguments: none
+ *
+ * Returns: char **
+ * The address of the first item in the return list
+ */
+
+static char **
+buildreturnlist(void)
+{
+ /* Automatic data */
+ char **list;
+ char **q;
+ struct deviceent *p;
+
+
+ /*
+ * Allocate space for the return list,
+ * with space for the terminating node
+ */
+
+ if (list = malloc((devicelist.count+1)*sizeof (char *))) {
+
+ /*
+ * Walk the list of accumulated devices, putting pointers to
+ * device names in the list to return
+ */
+
+ q = list;
+ for (p = devicelist.head->next; p; p = p->next) *q++ = p->name;
+
+ /* End the list with a null-pointer */
+ *q = NULL;
+ }
+
+
+ /* Return a pointer to the list we've built */
+ return (list);
+}
+
+/*
+ * char **makealiaslist(devices)
+ * char **devices List of aliases
+ *
+ * Builds a list of aliases of the devices in the "devices"
+ * list. This list will be terminated by (char *) NULL and
+ * will have the same number of elements as "devices". If
+ * a device couldn't be found, that alias will be "". There
+ * will be a one-to-one correspondence of devices to aliases
+ * in the device list "devices" and the generated list.
+ *
+ * Arguments:
+ * devices The list of devices to derive aliases from
+ *
+ * Returns: char **
+ * The address of the list of addresses of aliases. The list
+ * and aliases will be allocated using the malloc() function.
+ */
+
+static char **
+makealiaslist(char **devices)
+{
+ /* Automatic data */
+ char **pp; /* Running ptr to (char *) */
+ char **qq; /* Running ptr to (char *) */
+ char **aliases; /* List being returned */
+ char *alias; /* Alias of current device */
+ int olderrno; /* Value of errno on entry */
+ int noerror; /* Flag, TRUE if all's well */
+ int n; /* Count of entries in "devices" */
+
+
+ noerror = TRUE;
+ olderrno = errno;
+ if (devices) {
+
+ /* Get the number of entries in the constaint list */
+ for (n = 1, pp = devices; *pp; pp++) n++;
+
+ /* Get space for the alias list */
+ if (aliases = malloc(n*sizeof (char *))) {
+
+ /* Build the alias list */
+ qq = aliases;
+ for (pp = devices; noerror && *pp; pp++) {
+
+ /* Get the device's alias and put it in the list */
+ if (alias = devattr(*pp, DTAB_ALIAS)) *qq++ = alias;
+ else {
+ errno = olderrno;
+ if (alias = malloc(strlen("")+1))
+ *qq++ = strcpy(alias, "");
+ else {
+ /* No space for a null string? Yeech... */
+ for (qq = aliases; *qq; qq++) free(*qq);
+ free(aliases);
+ aliases = NULL;
+ noerror = FALSE;
+ }
+ }
+ }
+ if (noerror)
+ *qq = NULL;
+
+ }
+
+ } else
+ aliases = NULL; /* No constraint list */
+
+ /* Return ptr to generated list or NULL if none or error */
+ return (aliases);
+}
+
+/*
+ * void freealiaslist(aliaslist)
+ * char **aliaslist;
+ *
+ * Free the space allocated to the aliaslist. It frees the space
+ * allocated to the character-strings referenced by the list then
+ * it frees the list.
+ *
+ * Arguments:
+ * aliaslist The address of the first item in the list of
+ * aliases that is to be freed
+ *
+ * Returns: void
+ */
+
+static void
+freealiaslist(char **aliaslist) /* Ptr to new device list */
+{
+ /* Automatic Data */
+ char **pp; /* Running pointer */
+
+ /* If there's a list ... */
+ if (aliaslist) {
+
+ /* For each entry in the old list, free the entry */
+ for (pp = aliaslist; *pp; pp++) free(*pp);
+
+ /* Free the list */
+ free(aliaslist);
+ }
+}
+
+/*
+ * char *getnextmatch(criteria, options)
+ * struct srch *criteria
+ * int options
+ *
+ * Gets the next device in the device table that matches the criteria.
+ * Returns the alias of that device.
+ *
+ * Arguments:
+ * criteria The linked list of criteria to use to match a device
+ * options Options modifying the criteria (only one that's really
+ * important is the DTAB_ANDCRITERIA flag)
+ *
+ * Returns: char *
+ * A pointer to a malloc()ed string containing the alias of the next
+ * device that matches the criteria, or (char *) NULL if none.
+ */
+
+static char *
+getnextmatch(struct srch *criteria, int options)
+{
+ /* Automatic data */
+ struct devtabent *devtabent; /* Ptr to current record */
+ char *alias; /* Alias of device found */
+ int notdone; /* Flag, done yet? */
+ int noerror; /* Flag, had an error yet? */
+
+
+ /*
+ * Initializations:
+ * - No alias yet
+ * - Not finished yet
+ * - Make sure there are criteria we're to use
+ */
+
+ alias = NULL;
+ notdone = TRUE;
+ noerror = TRUE;
+
+ /* If we're to "and" the criteria... */
+ if (options & DTAB_ANDCRITERIA) {
+
+ /*
+ * Search the device table until we've got a record that matches
+ * all of the criteria or we run out of records
+ */
+
+ while (notdone && (devtabent = _getdevtabent())) {
+ if (!devtabent->comment) {
+ if (!criteria || matchallcriteria(devtabent, criteria)) {
+ if (alias = malloc(strlen(devtabent->alias)+1))
+ (void) strcpy(alias, devtabent->alias);
+ else noerror = FALSE;
+ notdone = FALSE;
+ }
+ }
+ _freedevtabent(devtabent);
+ }
+ } else {
+
+ /*
+ * Search the device table until we've got a record that matches
+ * any of the criteria or we run out of records
+ */
+
+ while (notdone && (devtabent = _getdevtabent())) {
+ if (!devtabent->comment) {
+ if (!criteria || matchanycriteria(devtabent, criteria)) {
+ if (alias = malloc(strlen(devtabent->alias)+1))
+ (void) strcpy(alias, devtabent->alias);
+ else noerror = FALSE;
+ notdone = FALSE;
+ }
+ }
+ _freedevtabent(devtabent);
+ }
+ }
+
+
+ /* Return pointer to extracted alias (or NULL if none) */
+ if ((alias == NULL) && noerror) errno = ENOENT;
+ return (alias);
+}
+
+/*
+ * int matchallcriteria(devtabent, criteria)
+ *
+ * This function examines the record contained in "devtabent" and
+ * determines if that record meets all of the criteria specified by
+ * "criteria".
+ *
+ * Arguments:
+ * struct devtabent *devtabent The device table entry to examine.
+ * struct srch *criteria The criteria to match.
+ *
+ * Returns: int
+ * Returns TRUE if the record matches criteria, FALSE otherwise.
+ */
+
+static int
+matchallcriteria(
+ struct devtabent *ent, /* Entry to check */
+ struct srch *criteria) /* Criteria governing match */
+{
+ /* Automatic data */
+ struct srch *p; /* Pointer to current criteria */
+ struct attrval *q; /* Pointer to current attr/val pair */
+ int notfound; /* TRUE if attr found in list */
+ int failed; /* TRUE if record failed to match */
+
+
+ /* Test only if there's criteria to test against */
+ if (criteria && (criteria->fcn != ENDLIST)) {
+
+ failed = FALSE;
+ for (p = criteria; !failed && (p->fcn != ENDLIST); p++) {
+
+ /*
+ * Don't compare against this criteria if it's function is
+ * "IGNORE"
+ */
+ if (p->fcn != IGNORE) {
+ if (p->fcn != NOEXISTS) {
+
+ /* Alias? */
+ if (strcmp(p->name, DTAB_ALIAS) == 0)
+ failed = !matches(ent->alias, p->cmp, p->fcn);
+
+ /* Char special device? */
+ else if (strcmp(p->name, DTAB_CDEVICE) == 0)
+ failed = !matches(ent->cdevice, p->cmp, p->fcn);
+
+ /* Block special device? */
+ else if (strcmp(p->name, DTAB_BDEVICE) == 0)
+ failed = !matches(ent->bdevice, p->cmp, p->fcn);
+
+ /* Pathname? */
+ else if (strcmp(p->name, DTAB_PATHNAME) == 0)
+ failed = !matches(ent->pathname, p->cmp, p->fcn);
+
+ /* Check other attributes... */
+ else {
+ notfound = TRUE;
+ q = ent->attrlist;
+ while (notfound && q) {
+ if (strcmp(p->name, q->attr) == 0) {
+ notfound = FALSE;
+ if (!matches(q->val, p->cmp, p->fcn))
+ failed = TRUE;
+ } else q = q->next;
+ }
+ if (notfound) failed = TRUE;
+ }
+ } else {
+ if (strcmp(p->name, DTAB_ALIAS) == 0) failed = TRUE;
+ else if (strcmp(p->name, DTAB_CDEVICE) == 0)
+ failed = FALSE;
+ else if (strcmp(p->name, DTAB_BDEVICE) == 0)
+ failed = FALSE;
+ else if (strcmp(p->name, DTAB_PATHNAME) == 0)
+ failed = FALSE;
+ else {
+ q = ent->attrlist;
+ while (!failed && q) {
+ if (strcmp(p->name, q->attr) == 0)
+ failed = TRUE;
+ else q = q->next;
+ }
+ }
+ }
+
+ } /* Search function is not "IGNORE" */
+
+ } /* for loop, checking each criteria */
+
+ } /* if (criteria) */
+
+ else failed = FALSE; /* No criteria specified, it's a match */
+
+
+ /* Return a value indicating if the record matches all criteria */
+ return (!failed);
+}
+
+/*
+ * int matchanycriteria(devtabent, criteria)
+ *
+ * This function examines the record contained in "devtabent" and
+ * determines if that record meets any of the criteria specified by
+ * "criteria".
+ *
+ * Arguments:
+ * struct devtabent *devtabent The device table entry to examine.
+ * struct srch *criteria The criteria to match.
+ *
+ * Returns: int
+ * Returns TRUE if the record matches criteria, FALSE otherwise.
+ */
+
+static int
+matchanycriteria(
+ struct devtabent *ent, /* Entry to check */
+ struct srch *criteria) /* Criteria governing match */
+{
+ /* Automatic data */
+ struct srch *p; /* Pointer to current criteria */
+ struct attrval *q; /* Pointer to current attr/val pair */
+ int matched; /* FLAG: TRUE if record matched */
+ int found; /* FLAG: TRUE if attribute found */
+
+
+ /* Test only if there's criteria to test against */
+ if (criteria && (criteria->fcn != ENDLIST)) {
+
+ matched = FALSE;
+ for (p = criteria; !matched && (p->fcn != ENDLIST); p++) {
+
+ /*
+ * Don't compare against this criteria if it's function is
+ * "IGNORE"
+ */
+ if (p->fcn != IGNORE) {
+ if (p->fcn != NOEXISTS) {
+
+ /* Alias? */
+ if (strcmp(p->name, DTAB_ALIAS) == 0)
+ matched = matches(ent->alias, p->cmp, p->fcn);
+
+ /* Char special device? */
+ else if (strcmp(p->name, DTAB_CDEVICE) == 0)
+ matched = matches(ent->cdevice, p->cmp, p->fcn);
+
+ /* Block special device? */
+ else if (strcmp(p->name, DTAB_BDEVICE) == 0)
+ matched = matches(ent->bdevice, p->cmp, p->fcn);
+
+ /* Pathname? */
+ else if (strcmp(p->name, DTAB_PATHNAME) == 0)
+ matched = matches(ent->pathname, p->cmp, p->fcn);
+
+ /* Check other attributes... */
+ else {
+ q = ent->attrlist;
+ found = FALSE;
+ while (!found && q)
+ if (strcmp(p->name, q->attr) == 0) {
+ matched = matches(q->val, p->cmp, p->fcn);
+ found = TRUE;
+ } else q = q->next;
+ }
+ } else {
+ if (strcmp(p->name, DTAB_ALIAS) == 0) matched = FALSE;
+ else if (strcmp(p->name, DTAB_CDEVICE) == 0)
+ matched = FALSE;
+ else if (strcmp(p->name, DTAB_BDEVICE) == 0)
+ matched = FALSE;
+ else if (strcmp(p->name, DTAB_PATHNAME) == 0)
+ matched = FALSE;
+ else {
+ q = ent->attrlist;
+ matched = TRUE;
+ while (matched && q) {
+ if (strcmp(p->name, q->attr) == 0)
+ matched = FALSE;
+ else q = q->next;
+ }
+ }
+ }
+ } /* Search function is not "IGNORE" */
+
+ } /* for loop, checking each criteria */
+
+ } /* if (criteria) */
+
+ else matched = TRUE; /* No criteria specified, it's a match */
+
+
+ /* Return a value indicating if the record matches all criteria */
+ return (matched);
+}
+
+/*
+ * int matches(value, compare, function)
+ * char *value
+ * char *compare
+ * int function
+ *
+ * This function sees if the operation <function> is satisfied by
+ * comparing the value <value> with <compare>. It returns TRUE
+ * if so, FALSE otherwise.
+ *
+ * Arguments:
+ * value Value to compare
+ * compare Value to compare against
+ * function Function to be satisfied
+ *
+ * Returns: int
+ * TRUE if the function is satisfied, FALSE otherwise
+ */
+
+static int
+matches(char *value, char *compare, int function)
+{
+ /* Automatic data */
+ int rtn; /* Value to return */
+
+
+ if (value == NULL)
+ value = "";
+
+ /* Do case depending on the function */
+ switch (function) {
+
+ /* attr=val */
+ case EQUAL:
+ rtn = (strcmp(value, compare) == 0);
+ break;
+
+ /* attr!=val */
+ case NOTEQUAL:
+ rtn = (strcmp(value, compare) != 0);
+ break;
+
+ /* attr:* */
+ case EXISTS:
+ rtn = TRUE;
+ break;
+
+ /* attr!:* */
+ case NOEXISTS:
+ rtn = FALSE;
+ break;
+
+ /* Shouldn't get here... */
+ default:
+ rtn = FALSE;
+ break;
+ }
+
+ /* Return a value indicating if the match was made */
+ return (rtn);
+}