/*
* 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);
}