/*
* 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
* 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:
* <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 <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
#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 ENDLIST 0
/*
* Structure definitions:
* deviceent Defines a device that matches criteria
* srch Describes a criteria
*/
struct deviceent {
};
struct srch {
};
/*
* 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 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 {
int count;
/*
* 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 **
char **devices, /* List of devices to constrain */
char **criteria, /* List of selection criteria */
int options) /* Options governing the search */
{
/* Automatic data */
/*
* Initializations
*/
return (NULL);
/* Build the search list */
if (criteria) {
return (NULL);
} else searchlist = NULL;
/* Initialize searching */
_setdevtab();
/*
* Keep on going until we get no more matches
*/
}
}
/*
* 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.
*/
_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 *
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 */
/* If there's a constraint list, is this device in it? */
/* Set "found" to TRUE if the device is in the list */
else {
devices++;
aliases++;
}
}
/* Set value to return */
if (found)
else
devtabentry : NULL;
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.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 */
/* List has a dummy head node */
while (pdevice) {
}
}
/*
* 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
{
/* Automatic data */
struct deviceent *p; /* Pointer to current device */
struct deviceent *q; /* Pointer to next device */
/* Initializations */
/*
* Find the place in the found device list devicelist where this
* device is to reside
*/
p = devicelist.head;
while (!done) {
q = p->next;
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 */
/* Alloc space for the device character string */
/*
* Insert an entry in the found device list containing
* this device name
*/
devicelist.count++;
}
/* Couldn't alloc space for the device name. Error. */
}
/* Couldn't alloc space for new node in the found list. Error. */
}
/* 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 *
{
/* Automatic data */
char *p; /* Temp pointer to char */
int n; /* Temp counter */
/* Initializations */
/* If we were given any criteria ... */
if (criteria) {
/* Count the number of criteria in the list */
;
/* Allocate space for structures describing the criteria */
/* Build structures describing the criteria */
/* Keep list sane for cleanup if necessary */
/* Alloc space for strings referenced by the structure */
/* Extract field name, function, and compare string */
/* If criteria contains an equal sign ('=') ... */
if (*(p-1) == '!') {
*(p-1) = '\0';
} else {
*p = '\0';
}
psrch++;
}
/* If criteria contains a colon (':') ... */
if (*(p-1) == '!') {
*(p-1) = '\0';
} else {
*p = '\0';
}
psrch++;
}
} else {
/* Unable to malloc() string space. Clean up */
}
/* Next criteria */
pp++;
}
/* Terminate list */
}
}
/* 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
{
/* Automatic data */
/* Free all of the string space allocated for the structure elememts */
}
/* Free the list space */
}
/*
* 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
*/
/*
* Walk the list of accumulated devices, putting pointers to
* device names in the list to return
*/
q = list;
/* 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 **
{
/* Automatic data */
int n; /* Count of entries in "devices" */
if (devices) {
/* Get the number of entries in the constaint list */
/* Get space for the alias list */
/* Build the alias list */
/* Get the device's alias and put it in the list */
else {
else {
/* No space for a null string? Yeech... */
}
}
}
if (noerror)
}
} else
/* 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
{
/* Automatic Data */
/* If there's a list ... */
if (aliaslist) {
/* For each entry in the old list, free the entry */
/* Free the list */
}
}
/*
* 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 *
{
/* Automatic data */
/*
* Initializations:
* - No alias yet
* - Not finished yet
* - Make sure there are criteria we're to use
*/
/* 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
*/
}
}
}
} else {
/*
* Search the device table until we've got a record that matches
* any of the criteria or we run out of records
*/
}
}
}
}
/* Return pointer to extracted alias (or NULL if none) */
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
{
/* Automatic data */
struct srch *p; /* Pointer to current criteria */
/* Test only if there's criteria to test against */
/*
* Don't compare against this criteria if it's function is
* "IGNORE"
*/
/* Alias? */
/* Char special device? */
/* Block special device? */
/* Pathname? */
/* Check other attributes... */
else {
while (notfound && q) {
} else q = q->next;
}
}
} else {
else {
while (!failed && q) {
else q = q->next;
}
}
}
} /* Search function is not "IGNORE" */
} /* for loop, checking each criteria */
} /* if (criteria) */
/* 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
{
/* Automatic data */
struct srch *p; /* Pointer to current criteria */
/* Test only if there's criteria to test against */
/*
* Don't compare against this criteria if it's function is
* "IGNORE"
*/
/* Alias? */
/* Char special device? */
/* Block special device? */
/* Pathname? */
/* Check other attributes... */
else {
while (!found && q)
} else q = q->next;
}
} else {
else {
while (matched && q) {
else q = q->next;
}
}
}
} /* Search function is not "IGNORE" */
} /* for loop, checking each criteria */
} /* if (criteria) */
/* 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
{
/* Automatic data */
value = "";
/* Do case depending on the function */
switch (function) {
/* attr=val */
case EQUAL:
break;
/* attr!=val */
case NOTEQUAL:
break;
/* attr:* */
case EXISTS:
break;
/* attr!:* */
case NOEXISTS:
break;
/* Shouldn't get here... */
default:
break;
}
/* Return a value indicating if the match was made */
return (rtn);
}