summaryrefslogtreecommitdiff
path: root/usr/src/lib/libadm/common/dgrpent.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr/src/lib/libadm/common/dgrpent.c')
-rw-r--r--usr/src/lib/libadm/common/dgrpent.c661
1 files changed, 661 insertions, 0 deletions
diff --git a/usr/src/lib/libadm/common/dgrpent.c b/usr/src/lib/libadm/common/dgrpent.c
new file mode 100644
index 0000000000..0e48c9a1b8
--- /dev/null
+++ b/usr/src/lib/libadm/common/dgrpent.c
@@ -0,0 +1,661 @@
+/*
+ * 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,1998,2002 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+
+#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */
+/*LINTLIBRARY*/
+
+/*
+ * dgrpent.c
+ *
+ * Contains functions that deal with the device-group table and are not for
+ * consumption by the general user population.
+ *
+ * Functions defined:
+ * _opendgrptab() Opens the device-group table for commands
+ * _setdgrptab() Rewinds the open device table
+ * _enddgrptab() Closes the open device table
+ * _getdgrptabent() Gets the next entry in the device table
+ * _freedgrptabent() Frees memory allocated to a device-table entry
+ * _getdgrprec() Gets a specific record from the device table
+ * _dgrptabpath() Gets the pathname of the device group file
+ */
+
+/*
+ * Header files
+ * <sys/types.h> System data types
+ * <unistd.h> Standard UNIX(r) definitions
+ * <stdio.h> Standard I/O Definitions
+ * <string.h> String handling definitions
+ * <ctype.h> Character types and macros
+ * <errno.h> Errorcode definitions
+ * <sys/stat.h> File status information
+ * <devmgmt.h> Global Device Management definitions
+ * "devtab.h" Local device table definitions
+ */
+
+#include <sys/types.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <devmgmt.h>
+#include "devtab.h"
+#include <stdlib.h>
+
+/*
+ * Local definitions
+ */
+
+
+/*
+ * Static data definitions:
+ * leftoff Addr of char to begin next parse using
+ * getfld(), getattrval(), getquoted()
+ * recbufsz The size of the buffer used for reading records
+ * recbuf Addr of malloc() buffer for reading records
+ * recnum Record number of next record to read
+ * xtndcnt Number of times the buffer has been extended
+ */
+
+static char *leftoff = NULL;
+static int recbufsz = 0;
+static char *recbuf = NULL;
+static int recnum = 0;
+static int xtndcnt = 0;
+
+/*
+ * void _setdgrptab()
+ *
+ * This function rewinds the open device table so that the next
+ * _getdgrptabent() returns the first record in the device table.
+ *
+ * Arguments: None
+ *
+ * Returns: Void
+ */
+
+void
+_setdgrptab(void)
+{
+ /* If the device table file is open, rewind the file */
+ if (oam_dgroup) {
+ rewind(oam_dgroup);
+ recnum = 0;
+ }
+}
+
+/*
+ * void _enddgrptab()
+ *
+ * This function closes the open device table. It resets the
+ * open device table external variable to NULL.
+ *
+ * Arguments: None
+ *
+ * Returns: Void
+ */
+
+void
+_enddgrptab(void)
+{
+ /* If the device table file is open, close it */
+ if (oam_dgroup) {
+ (void) fclose(oam_dgroup);
+ recnum = 0;
+ oam_dgroup = NULL;
+ }
+}
+
+/*
+ * char *getfld(ptr, delims)
+ * char *ptr
+ * char *delims
+ *
+ * Notes:
+ * - Can't use "strtok()" because of its use of static data. The caller
+ * may be using strtok() and we'll really mess them up.
+ * - The function returns NULL if it didn't find any token -- '\0' can't
+ * be a delimiter using this algorithm.
+ */
+
+static char *
+getfld(
+ char *ptr, /* String to parse */
+ char *delims) /* List of delimiters */
+{
+ char *p, *q;
+
+ /*
+ * Figure out where to start.
+ * If given a pointer, use that.
+ * Otherwise, use where we left off.
+ */
+
+ p = ptr ? ptr : leftoff;
+
+
+ /*
+ * If there's anything to parse, search the string for the first
+ * occurrence of any of the delimiters. If one is found, change it
+ * to '\0' and remember the place to start for next time. If not
+ * found, forget the restart address and prepare to return NULL
+ */
+
+ if (p) {
+ while (*p && isspace((unsigned char)*p)) p++;
+ if (*p) {
+ q = p;
+ while (*q && !strchr(delims, *q)) q++;
+ if (*q) {
+ *q++ = '\0';
+ leftoff = q;
+ } else leftoff = NULL;
+ } else leftoff = p = NULL;
+ }
+
+ /* Finished */
+ return (p);
+}
+
+/*
+ * char *getnextrec()
+ *
+ * This function gets the next record from the input stream "oam_dgroup"
+ * and puts it in the device-group table record buffer (whose address is
+ * in "recbuf"). If the buffer is not allocated or is too small to
+ * accommodate the record, the function allocates more space to the
+ * buffer.
+ *
+ * Arguments: None
+ *
+ * Returns: char *
+ * The address of the buffer containing the record.
+ *
+ * Static Data Referenced:
+ * recbuf Address of the buffer containing records read from the
+ * device table file
+ * recbufsz Current size of the record buffer
+ * xtndcnt Number of times the record buffer has been extended
+ * oam_dgroup Device-group table stream, expected to be open for (at
+ * least) reading
+ *
+ * Notes:
+ * - The string returned in the buffer <buf> ALWAYS end in a '\n' (newline)
+ * character followed by a '\0' (null).
+ */
+
+static char *
+getnextrec(void)
+{
+ /* Automatic data */
+ char *recp; /* Value to return */
+ char *p; /* Temp pointer */
+ int done; /* TRUE if we're finished */
+ int reclen; /* Number of chars in record */
+
+
+ /* If there's no buffer for records, try to get one */
+ if (!recbuf) {
+ if (recbuf = malloc(DGRP_BUFSIZ)) {
+ recbufsz = DGRP_BUFSIZ;
+ xtndcnt = 0;
+ } else return (NULL);
+ }
+
+
+ /* Get the next record */
+ recp = fgets(recbuf, recbufsz, oam_dgroup);
+ done = FALSE;
+
+ /* While we've something to return and we're not finished ... */
+ while (recp && !done) {
+
+ /* If our return string isn't a null-string ... */
+ if ((reclen = (int)strlen(recp)) != 0) {
+
+ /* If we have a complete record, we're finished */
+ if (*(recp+reclen-1) == '\n') done = TRUE;
+ else while (!done) {
+
+ /*
+ * Need to complete the record. A complete record is one
+ * which is terminated by a new-line character
+ */
+
+ /* If the buffer is full, expand it and continue reading */
+ if (reclen == recbufsz-1) {
+
+ /* Have we reached our maximum extension count? */
+ if (xtndcnt < XTND_MAXCNT) {
+
+ /* Expand the record buffer */
+ if (p = realloc(recbuf,
+ (size_t)(recbufsz+DGRP_BUFINC))) {
+
+ /* Update buffer information */
+ xtndcnt++;
+ recbuf = p;
+ recbufsz += DGRP_BUFINC;
+
+ } else {
+
+ /* Expansion failed */
+ recp = NULL;
+ done = TRUE;
+ }
+
+ } else {
+
+ /* Maximum extend count exceeded. Insane table */
+ recp = NULL;
+ done = TRUE;
+ }
+
+ }
+
+ /* Complete the record */
+ if (!done) {
+
+ /* Read stuff into the expanded space */
+ if (fgets(recbuf+reclen, recbufsz-reclen, oam_dgroup)) {
+ reclen = (int)strlen(recbuf);
+ recp = recbuf;
+ if (*(recp+reclen-1) == '\n') done = TRUE;
+ } else {
+ /* Read failed, corrupt record? */
+ recp = NULL;
+ done = TRUE;
+ }
+ }
+
+ } /* End incomplete record handling */
+
+ } else {
+
+ /* Read a null string? (corrupt table) */
+ recp = NULL;
+ done = TRUE;
+ }
+
+ } /* while (recp && !done) */
+
+ /* Return what we've got (if anything) */
+ return (recp);
+}
+
+/*
+ * char *_dgrptabpath()
+ *
+ * Get the pathname of the device-group table file
+ *
+ * Arguments: None
+ *
+ * Returns: char *
+ * Returns the pathname to the device group table of (char *) NULL if
+ * there was a problem getting the memory needed to contain the
+ * pathname.
+ *
+ * Algorithm:
+ * 1. If OAM_DGRP is defined in the environment and is not
+ * defined as "", it returns the value of that environment
+ * variable.
+ * 2. Otherwise, use the devault pathname (as defined by the
+ * environment variable DGRP_PATH in <devmgmt.h>.
+ */
+
+
+char *
+_dgrptabpath(void)
+{
+
+ /* Automatic data */
+#ifdef DEBUG
+ char *path; /* Ptr to path in environment */
+#endif
+ char *rtnval; /* Ptr to value to return */
+
+
+ /*
+ * If compiled with -DDEBUG=1,
+ * look for the pathname in the environment
+ */
+
+#ifdef DEBUG
+ if (((path = getenv(OAM_DGROUP)) != NULL) && (*path)) {
+ if (rtnval = malloc(strlen(path)+1))
+ (void) strcpy(rtnval, path);
+ } else {
+#endif
+ /*
+ * Use the default name.
+ */
+
+ if (rtnval = malloc(strlen(DGRP_PATH)+1))
+ (void) strcpy(rtnval, DGRP_PATH);
+
+#ifdef DEBUG
+ }
+#endif
+
+ /* Finished */
+ return (rtnval);
+}
+
+/*
+ * int _opendgrptab(mode)
+ * char *mode
+ *
+ * The _opendgrptab() function opens a device-group table for a command.
+ *
+ * Arguments:
+ * mode The open mode to use to open the file. (i.e. "r" for
+ * reading, "w" for writing. See FOPEN(BA_OS) in SVID.)
+ *
+ * Returns: int
+ * TRUE if successful, FALSE otherwise
+ */
+
+int
+_opendgrptab(char *mode)
+{
+ /* Automatic data */
+ char *dgrptabname; /* Ptr to the device-group table name */
+ int rtnval; /* Value to return */
+
+ rtnval = TRUE;
+ if (dgrptabname = _dgrptabpath()) {
+ if (oam_dgroup) (void) fclose(oam_dgroup);
+ if (oam_dgroup = fopen(dgrptabname, mode)) {
+ xtndcnt = 0;
+ recnum = 0;
+ } else rtnval = FALSE; /* :-( */
+ } else rtnval = FALSE; /* :-( */
+ return (rtnval);
+}
+
+/*
+ * struct dgrptabent *_getdgrptabent()
+ *
+ * This function returns the next entry in the device-group table.
+ * If no device-group table is open, it opens the standard device-group
+ * table and returns the first record in the table.
+ *
+ * Arguments: None.
+ *
+ * Returns: struct dgrptabent *
+ * Pointer to the next record in the device-group table, or
+ * (struct dgrptabent *) NULL if it was unable to open the file or there
+ * are no more records to read. "errno" reflects the situation. If
+ * errno is not changed and the function returns NULL, there are no more
+ * records to read. If errno is set, it indicates the error.
+ *
+ * Notes:
+ * - The caller should set "errno" to 0 before calling this function.
+ */
+
+struct dgrptabent *
+_getdgrptabent(void)
+{
+ /* Automatic data */
+ struct dgrptabent *ent; /* Dev table entry structure */
+ struct member *q, *r; /* Tmps for member structs */
+ char *record; /* Record just read */
+ char *p; /* Tmp char ptr */
+ int done; /* TRUE if built an entry */
+
+
+ /* Open the device-group table if it's not already open */
+ if (!oam_dgroup)
+ if (!_opendgrptab("r"))
+ return (NULL);
+
+
+ /* Get space for the structure we're returning */
+ if (!(ent = malloc(sizeof (struct dgrptabent)))) {
+ return (NULL);
+ }
+
+ done = FALSE;
+ while (!done && (record = getnextrec())) {
+
+ /* Is this a comment record or a data record */
+ if (strchr("#\n", *record) ||
+ isspace((unsigned char)*record)) {
+
+ /*
+ * Record is a comment record
+ */
+ ent->comment = TRUE;
+ ent->entryno = recnum++;
+
+ /* Alloc space for the comment and save pointer in struct */
+ if (ent->dataspace = malloc(strlen(record)+1)) {
+ (void) strcpy(ent->dataspace, record);
+ } else {
+ free(ent);
+ ent = NULL;
+ }
+ done = TRUE;
+
+ } else {
+
+ /*
+ * Record is a data record
+ */
+ ent->comment = FALSE;
+
+ /* Extract the device-group name */
+ if (p = getfld(record, ":")) {
+
+ /* Record is a proper record */
+ done = TRUE;
+ ent->entryno = recnum++;
+
+ /* Copy device group name into malloc()ed space */
+ if (!(ent->name = malloc(strlen(p)+1))) {
+
+ free(ent);
+ return (NULL);
+ }
+ (void) strcpy(ent->name, p);
+
+ /*
+ * Extract the membership from the membership list
+ */
+
+ /* Get the 1st member */
+ ent->dataspace = NULL;
+ while (((p = getfld(NULL, ",\n")) != NULL) && !(*p))
+ ;
+ if (p) {
+ if (!(q = malloc(sizeof (struct member)))) {
+
+ free(ent->name);
+ free(ent);
+ return (NULL);
+ }
+ if (!(q->name = malloc(strlen(p)+1))) {
+ free(q);
+ free(ent->name);
+ free((char *)ent);
+ return (NULL);
+ }
+ (void) strcpy(q->name, p);
+ ent->membership = q;
+ q->next = NULL;
+
+ /* Get the rest of the members */
+ while (p = getfld(NULL, ",\n"))
+ if (*p) {
+ if (!(r = malloc(sizeof (struct member)))) {
+ for (q = ent->membership; q; q = r) {
+ free(q->name);
+ r = q->next;
+ free(q);
+ }
+ free(ent->name);
+ free(ent);
+ return (NULL);
+ }
+ if (!(r->name = malloc(strlen(p)+1))) {
+ free(r);
+ for (q = ent->membership; q; q = r) {
+ free(q->name);
+ r = q->next;
+ free(q);
+ }
+ free(ent->name);
+ free(ent);
+ return (NULL);
+ }
+
+ q->next = r;
+ (void) strcpy(r->name, p);
+ r->next = NULL;
+ q = r;
+ }
+
+ } else {
+ /* No members */
+ ent->membership = NULL;
+ }
+
+ } /* record contains a group name */
+
+ } /* record is a data record */
+
+ } /* while (!done && there's more records) */
+
+
+ /* An entry read? If not, free alloc'd space and return NULL */
+ if (!done) {
+ free(ent);
+ ent = NULL;
+ }
+
+ /* Finis */
+ return (ent);
+}
+
+/*
+ * void _freedgrptabent(dgrptabent)
+ * struct dgrptabent *dgrptabent;
+ *
+ * This function frees space allocated to a device table entry.
+ *
+ * Arguments:
+ * struct dgrptabent *dgrptabent The structure whose space is to be
+ * freed.
+ *
+ * Returns: void
+ */
+
+void
+_freedgrptabent(struct dgrptabent *ent) /* Structure to free */
+{
+ /*
+ * Automatic data
+ */
+
+ struct member *p; /* Structure being freed */
+ struct member *q; /* Next structure to free */
+
+ /*
+ * Free the space allocated to the membership structure.
+ */
+
+ if (!ent->comment) {
+ if ((q = ent->membership) != NULL) do {
+ p = q;
+ q = p->next;
+ if (p->name) free(p->name);
+ free(p);
+ } while (q);
+
+ /* Free the device group name */
+ if (ent->name) free(ent->name);
+ }
+
+ /* Free the membership string */
+ if (ent->dataspace) free(ent->dataspace);
+}
+
+/*
+ * struct dgrptabent *_getdgrprec(dgroup)
+ * char *dgroup
+ *
+ * Thie _getdgrprec() function returns a pointer to a structure that
+ * contains the information in the device-group table entry that describes
+ * the device-group <dgroup>.
+ *
+ * Arguments:
+ * char *dgroup A character-string describing the device-group whose
+ * record is to be retrieved from the device-group table.
+ *
+ * Returns: struct dgrptabent *
+ * A pointer to a structure describing the device group.
+ */
+
+struct dgrptabent *
+_getdgrprec(char *dgroup) /* dgroup to search for */
+{
+ /*
+ * Automatic data
+ */
+
+ struct dgrptabent *dgrprec; /* Pointer to current record */
+ int found; /* FLAG, TRUE if found */
+
+
+ /*
+ * Search the device-group table looking for the requested
+ * device group
+ */
+
+ _setdgrptab();
+ errno = 0;
+ found = FALSE;
+ while (!found && (dgrprec = _getdgrptabent())) {
+ if (!dgrprec->comment && strcmp(dgroup, dgrprec->name) == 0)
+ found = TRUE;
+ else _freedgrptabent(dgrprec);
+ }
+
+ /* Set up return codes if we've failed */
+ if (!found) {
+ if (errno == 0) errno = EINVAL;
+ dgrprec = NULL;
+ }
+
+ /* Finis */
+ return (dgrprec);
+}