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
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.
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]
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
27 * Copyright (c) 1997,1998,2002 by Sun Microsystems, Inc.
28 * All rights reserved.
36 * Contains functions that deal with the device-group table and are not for
37 * consumption by the general user population.
40 * _opendgrptab() Opens the device-group table for commands
41 * _setdgrptab() Rewinds the open device table
42 * _enddgrptab() Closes the open device table
43 * _getdgrptabent() Gets the next entry in the device table
44 * _freedgrptabent() Frees memory allocated to a device-table entry
45 * _getdgrprec() Gets a specific record from the device table
46 * _dgrptabpath() Gets the pathname of the device group file
51 * <sys/types.h> System data types
52 * <unistd.h> Standard UNIX(r) definitions
53 * <stdio.h> Standard I/O Definitions
54 * <string.h> String handling definitions
55 * <ctype.h> Character types and macros
56 * <errno.h> Errorcode definitions
57 * <sys/stat.h> File status information
58 * <devmgmt.h> Global Device Management definitions
59 * "devtab.h" Local device table definitions
62 #include <sys/types.h>
79 * Static data definitions:
80 * leftoff Addr of char to begin next parse using
81 * getfld(), getattrval(), getquoted()
82 * recbufsz The size of the buffer used for reading records
83 * recbuf Addr of malloc() buffer for reading records
84 * recnum Record number of next record to read
85 * xtndcnt Number of times the buffer has been extended
88 static char *leftoff
= NULL
;
89 static int recbufsz
= 0;
90 static char *recbuf
= NULL
;
91 static int recnum
= 0;
92 static int xtndcnt
= 0;
97 * This function rewinds the open device table so that the next
98 * _getdgrptabent() returns the first record in the device table.
108 /* If the device table file is open, rewind the file */
118 * This function closes the open device table. It resets the
119 * open device table external variable to NULL.
129 /* If the device table file is open, close it */
131 (void) fclose(oam_dgroup
);
138 * char *getfld(ptr, delims)
143 * - Can't use "strtok()" because of its use of static data. The caller
144 * may be using strtok() and we'll really mess them up.
145 * - The function returns NULL if it didn't find any token -- '\0' can't
146 * be a delimiter using this algorithm.
151 char *ptr
, /* String to parse */
152 char *delims
) /* List of delimiters */
157 * Figure out where to start.
158 * If given a pointer, use that.
159 * Otherwise, use where we left off.
162 p
= ptr
? ptr
: leftoff
;
166 * If there's anything to parse, search the string for the first
167 * occurrence of any of the delimiters. If one is found, change it
168 * to '\0' and remember the place to start for next time. If not
169 * found, forget the restart address and prepare to return NULL
173 while (*p
&& isspace((unsigned char)*p
)) p
++;
176 while (*q
&& !strchr(delims
, *q
)) q
++;
180 } else leftoff
= NULL
;
181 } else leftoff
= p
= NULL
;
191 * This function gets the next record from the input stream "oam_dgroup"
192 * and puts it in the device-group table record buffer (whose address is
193 * in "recbuf"). If the buffer is not allocated or is too small to
194 * accommodate the record, the function allocates more space to the
200 * The address of the buffer containing the record.
202 * Static Data Referenced:
203 * recbuf Address of the buffer containing records read from the
205 * recbufsz Current size of the record buffer
206 * xtndcnt Number of times the record buffer has been extended
207 * oam_dgroup Device-group table stream, expected to be open for (at
211 * - The string returned in the buffer <buf> ALWAYS end in a '\n' (newline)
212 * character followed by a '\0' (null).
219 char *recp
; /* Value to return */
220 char *p
; /* Temp pointer */
221 int done
; /* TRUE if we're finished */
222 int reclen
; /* Number of chars in record */
225 /* If there's no buffer for records, try to get one */
227 if (recbuf
= malloc(DGRP_BUFSIZ
)) {
228 recbufsz
= DGRP_BUFSIZ
;
230 } else return (NULL
);
234 /* Get the next record */
235 recp
= fgets(recbuf
, recbufsz
, oam_dgroup
);
238 /* While we've something to return and we're not finished ... */
239 while (recp
&& !done
) {
241 /* If our return string isn't a null-string ... */
242 if ((reclen
= (int)strlen(recp
)) != 0) {
244 /* If we have a complete record, we're finished */
245 if (*(recp
+reclen
-1) == '\n') done
= TRUE
;
249 * Need to complete the record. A complete record is one
250 * which is terminated by a new-line character
253 /* If the buffer is full, expand it and continue reading */
254 if (reclen
== recbufsz
-1) {
256 /* Have we reached our maximum extension count? */
257 if (xtndcnt
< XTND_MAXCNT
) {
259 /* Expand the record buffer */
260 if (p
= realloc(recbuf
,
261 (size_t)(recbufsz
+DGRP_BUFINC
))) {
263 /* Update buffer information */
266 recbufsz
+= DGRP_BUFINC
;
270 /* Expansion failed */
277 /* Maximum extend count exceeded. Insane table */
284 /* Complete the record */
287 /* Read stuff into the expanded space */
288 if (fgets(recbuf
+reclen
, recbufsz
-reclen
, oam_dgroup
)) {
289 reclen
= (int)strlen(recbuf
);
291 if (*(recp
+reclen
-1) == '\n') done
= TRUE
;
293 /* Read failed, corrupt record? */
299 } /* End incomplete record handling */
303 /* Read a null string? (corrupt table) */
308 } /* while (recp && !done) */
310 /* Return what we've got (if anything) */
315 * char *_dgrptabpath()
317 * Get the pathname of the device-group table file
322 * Returns the pathname to the device group table of (char *) NULL if
323 * there was a problem getting the memory needed to contain the
327 * 1. If OAM_DGRP is defined in the environment and is not
328 * defined as "", it returns the value of that environment
330 * 2. Otherwise, use the devault pathname (as defined by the
331 * environment variable DGRP_PATH in <devmgmt.h>.
341 char *path
; /* Ptr to path in environment */
343 char *rtnval
; /* Ptr to value to return */
347 * If compiled with -DDEBUG=1,
348 * look for the pathname in the environment
352 if (((path
= getenv(OAM_DGROUP
)) != NULL
) && (*path
)) {
353 if (rtnval
= malloc(strlen(path
)+1))
354 (void) strcpy(rtnval
, path
);
358 * Use the default name.
361 if (rtnval
= malloc(strlen(DGRP_PATH
)+1))
362 (void) strcpy(rtnval
, DGRP_PATH
);
373 * int _opendgrptab(mode)
376 * The _opendgrptab() function opens a device-group table for a command.
379 * mode The open mode to use to open the file. (i.e. "r" for
380 * reading, "w" for writing. See FOPEN(BA_OS) in SVID.)
383 * TRUE if successful, FALSE otherwise
387 _opendgrptab(char *mode
)
390 char *dgrptabname
; /* Ptr to the device-group table name */
391 int rtnval
; /* Value to return */
394 if (dgrptabname
= _dgrptabpath()) {
395 if (oam_dgroup
) (void) fclose(oam_dgroup
);
396 if (oam_dgroup
= fopen(dgrptabname
, mode
)) {
399 } else rtnval
= FALSE
; /* :-( */
400 } else rtnval
= FALSE
; /* :-( */
405 * struct dgrptabent *_getdgrptabent()
407 * This function returns the next entry in the device-group table.
408 * If no device-group table is open, it opens the standard device-group
409 * table and returns the first record in the table.
413 * Returns: struct dgrptabent *
414 * Pointer to the next record in the device-group table, or
415 * NULL if it was unable to open the file or there
416 * are no more records to read. "errno" reflects the situation. If
417 * errno is not changed and the function returns NULL, there are no more
418 * records to read. If errno is set, it indicates the error.
421 * - The caller should set "errno" to 0 before calling this function.
428 struct dgrptabent
*ent
; /* Dev table entry structure */
429 struct member
*q
, *r
; /* Tmps for member structs */
430 char *record
; /* Record just read */
431 char *p
; /* Tmp char ptr */
432 int done
; /* TRUE if built an entry */
435 /* Open the device-group table if it's not already open */
437 if (!_opendgrptab("r"))
441 /* Get space for the structure we're returning */
442 if (!(ent
= malloc(sizeof (struct dgrptabent
)))) {
447 while (!done
&& (record
= getnextrec())) {
449 /* Is this a comment record or a data record */
450 if (strchr("#\n", *record
) ||
451 isspace((unsigned char)*record
)) {
454 * Record is a comment record
457 ent
->entryno
= recnum
++;
459 /* Alloc space for the comment and save pointer in struct */
460 if (ent
->dataspace
= malloc(strlen(record
)+1)) {
461 (void) strcpy(ent
->dataspace
, record
);
471 * Record is a data record
473 ent
->comment
= FALSE
;
475 /* Extract the device-group name */
476 if (p
= getfld(record
, ":")) {
478 /* Record is a proper record */
480 ent
->entryno
= recnum
++;
482 /* Copy device group name into malloc()ed space */
483 if (!(ent
->name
= malloc(strlen(p
)+1))) {
488 (void) strcpy(ent
->name
, p
);
491 * Extract the membership from the membership list
494 /* Get the 1st member */
495 ent
->dataspace
= NULL
;
496 while (((p
= getfld(NULL
, ",\n")) != NULL
) && !(*p
))
499 if (!(q
= malloc(sizeof (struct member
)))) {
505 if (!(q
->name
= malloc(strlen(p
)+1))) {
511 (void) strcpy(q
->name
, p
);
515 /* Get the rest of the members */
516 while (p
= getfld(NULL
, ",\n"))
518 if (!(r
= malloc(sizeof (struct member
)))) {
519 for (q
= ent
->membership
; q
; q
= r
) {
528 if (!(r
->name
= malloc(strlen(p
)+1))) {
530 for (q
= ent
->membership
; q
; q
= r
) {
541 (void) strcpy(r
->name
, p
);
548 ent
->membership
= NULL
;
551 } /* record contains a group name */
553 } /* record is a data record */
555 } /* while (!done && there's more records) */
558 /* An entry read? If not, free alloc'd space and return NULL */
569 * void _freedgrptabent(dgrptabent)
570 * struct dgrptabent *dgrptabent;
572 * This function frees space allocated to a device table entry.
575 * struct dgrptabent *dgrptabent The structure whose space is to be
582 _freedgrptabent(struct dgrptabent
*ent
) /* Structure to free */
588 struct member
*p
; /* Structure being freed */
589 struct member
*q
; /* Next structure to free */
592 * Free the space allocated to the membership structure.
596 if ((q
= ent
->membership
) != NULL
) do {
603 /* Free the device group name */
607 /* Free the membership string */
608 free(ent
->dataspace
);
612 * struct dgrptabent *_getdgrprec(dgroup)
615 * Thie _getdgrprec() function returns a pointer to a structure that
616 * contains the information in the device-group table entry that describes
617 * the device-group <dgroup>.
620 * char *dgroup A character-string describing the device-group whose
621 * record is to be retrieved from the device-group table.
623 * Returns: struct dgrptabent *
624 * A pointer to a structure describing the device group.
628 _getdgrprec(char *dgroup
) /* dgroup to search for */
634 struct dgrptabent
*dgrprec
; /* Pointer to current record */
635 int found
; /* FLAG, TRUE if found */
639 * Search the device-group table looking for the requested
646 while (!found
&& (dgrprec
= _getdgrptabent())) {
647 if (!dgrprec
->comment
&& strcmp(dgroup
, dgrprec
->name
) == 0)
649 else _freedgrptabent(dgrprec
);
652 /* Set up return codes if we've failed */
654 if (errno
== 0) errno
= EINVAL
;