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.
31 #pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 1.1 */
37 * Contains functions that deal with the device-group table and are not for
38 * consumption by the general user population.
41 * _opendgrptab() Opens the device-group table for commands
42 * _setdgrptab() Rewinds the open device table
43 * _enddgrptab() Closes the open device table
44 * _getdgrptabent() Gets the next entry in the device table
45 * _freedgrptabent() Frees memory allocated to a device-table entry
46 * _getdgrprec() Gets a specific record from the device table
47 * _dgrptabpath() Gets the pathname of the device group file
52 * <sys/types.h> System data types
53 * <unistd.h> Standard UNIX(r) definitions
54 * <stdio.h> Standard I/O Definitions
55 * <string.h> String handling definitions
56 * <ctype.h> Character types and macros
57 * <errno.h> Errorcode definitions
58 * <sys/stat.h> File status information
59 * <devmgmt.h> Global Device Management definitions
60 * "devtab.h" Local device table definitions
63 #include <sys/types.h>
80 * Static data definitions:
81 * leftoff Addr of char to begin next parse using
82 * getfld(), getattrval(), getquoted()
83 * recbufsz The size of the buffer used for reading records
84 * recbuf Addr of malloc() buffer for reading records
85 * recnum Record number of next record to read
86 * xtndcnt Number of times the buffer has been extended
89 static char *leftoff
= NULL
;
90 static int recbufsz
= 0;
91 static char *recbuf
= NULL
;
92 static int recnum
= 0;
93 static int xtndcnt
= 0;
98 * This function rewinds the open device table so that the next
99 * _getdgrptabent() returns the first record in the device table.
109 /* If the device table file is open, rewind the file */
119 * This function closes the open device table. It resets the
120 * open device table external variable to NULL.
130 /* If the device table file is open, close it */
132 (void) fclose(oam_dgroup
);
139 * char *getfld(ptr, delims)
144 * - Can't use "strtok()" because of its use of static data. The caller
145 * may be using strtok() and we'll really mess them up.
146 * - The function returns NULL if it didn't find any token -- '\0' can't
147 * be a delimiter using this algorithm.
152 char *ptr
, /* String to parse */
153 char *delims
) /* List of delimiters */
158 * Figure out where to start.
159 * If given a pointer, use that.
160 * Otherwise, use where we left off.
163 p
= ptr
? ptr
: leftoff
;
167 * If there's anything to parse, search the string for the first
168 * occurrence of any of the delimiters. If one is found, change it
169 * to '\0' and remember the place to start for next time. If not
170 * found, forget the restart address and prepare to return NULL
174 while (*p
&& isspace((unsigned char)*p
)) p
++;
177 while (*q
&& !strchr(delims
, *q
)) q
++;
181 } else leftoff
= NULL
;
182 } else leftoff
= p
= NULL
;
192 * This function gets the next record from the input stream "oam_dgroup"
193 * and puts it in the device-group table record buffer (whose address is
194 * in "recbuf"). If the buffer is not allocated or is too small to
195 * accommodate the record, the function allocates more space to the
201 * The address of the buffer containing the record.
203 * Static Data Referenced:
204 * recbuf Address of the buffer containing records read from the
206 * recbufsz Current size of the record buffer
207 * xtndcnt Number of times the record buffer has been extended
208 * oam_dgroup Device-group table stream, expected to be open for (at
212 * - The string returned in the buffer <buf> ALWAYS end in a '\n' (newline)
213 * character followed by a '\0' (null).
220 char *recp
; /* Value to return */
221 char *p
; /* Temp pointer */
222 int done
; /* TRUE if we're finished */
223 int reclen
; /* Number of chars in record */
226 /* If there's no buffer for records, try to get one */
228 if (recbuf
= malloc(DGRP_BUFSIZ
)) {
229 recbufsz
= DGRP_BUFSIZ
;
231 } else return (NULL
);
235 /* Get the next record */
236 recp
= fgets(recbuf
, recbufsz
, oam_dgroup
);
239 /* While we've something to return and we're not finished ... */
240 while (recp
&& !done
) {
242 /* If our return string isn't a null-string ... */
243 if ((reclen
= (int)strlen(recp
)) != 0) {
245 /* If we have a complete record, we're finished */
246 if (*(recp
+reclen
-1) == '\n') done
= TRUE
;
250 * Need to complete the record. A complete record is one
251 * which is terminated by a new-line character
254 /* If the buffer is full, expand it and continue reading */
255 if (reclen
== recbufsz
-1) {
257 /* Have we reached our maximum extension count? */
258 if (xtndcnt
< XTND_MAXCNT
) {
260 /* Expand the record buffer */
261 if (p
= realloc(recbuf
,
262 (size_t)(recbufsz
+DGRP_BUFINC
))) {
264 /* Update buffer information */
267 recbufsz
+= DGRP_BUFINC
;
271 /* Expansion failed */
278 /* Maximum extend count exceeded. Insane table */
285 /* Complete the record */
288 /* Read stuff into the expanded space */
289 if (fgets(recbuf
+reclen
, recbufsz
-reclen
, oam_dgroup
)) {
290 reclen
= (int)strlen(recbuf
);
292 if (*(recp
+reclen
-1) == '\n') done
= TRUE
;
294 /* Read failed, corrupt record? */
300 } /* End incomplete record handling */
304 /* Read a null string? (corrupt table) */
309 } /* while (recp && !done) */
311 /* Return what we've got (if anything) */
316 * char *_dgrptabpath()
318 * Get the pathname of the device-group table file
323 * Returns the pathname to the device group table of (char *) NULL if
324 * there was a problem getting the memory needed to contain the
328 * 1. If OAM_DGRP is defined in the environment and is not
329 * defined as "", it returns the value of that environment
331 * 2. Otherwise, use the devault pathname (as defined by the
332 * environment variable DGRP_PATH in <devmgmt.h>.
342 char *path
; /* Ptr to path in environment */
344 char *rtnval
; /* Ptr to value to return */
348 * If compiled with -DDEBUG=1,
349 * look for the pathname in the environment
353 if (((path
= getenv(OAM_DGROUP
)) != NULL
) && (*path
)) {
354 if (rtnval
= malloc(strlen(path
)+1))
355 (void) strcpy(rtnval
, path
);
359 * Use the default name.
362 if (rtnval
= malloc(strlen(DGRP_PATH
)+1))
363 (void) strcpy(rtnval
, DGRP_PATH
);
374 * int _opendgrptab(mode)
377 * The _opendgrptab() function opens a device-group table for a command.
380 * mode The open mode to use to open the file. (i.e. "r" for
381 * reading, "w" for writing. See FOPEN(BA_OS) in SVID.)
384 * TRUE if successful, FALSE otherwise
388 _opendgrptab(char *mode
)
391 char *dgrptabname
; /* Ptr to the device-group table name */
392 int rtnval
; /* Value to return */
395 if (dgrptabname
= _dgrptabpath()) {
396 if (oam_dgroup
) (void) fclose(oam_dgroup
);
397 if (oam_dgroup
= fopen(dgrptabname
, mode
)) {
400 } else rtnval
= FALSE
; /* :-( */
401 } else rtnval
= FALSE
; /* :-( */
406 * struct dgrptabent *_getdgrptabent()
408 * This function returns the next entry in the device-group table.
409 * If no device-group table is open, it opens the standard device-group
410 * table and returns the first record in the table.
414 * Returns: struct dgrptabent *
415 * Pointer to the next record in the device-group table, or
416 * (struct dgrptabent *) NULL if it was unable to open the file or there
417 * are no more records to read. "errno" reflects the situation. If
418 * errno is not changed and the function returns NULL, there are no more
419 * records to read. If errno is set, it indicates the error.
422 * - The caller should set "errno" to 0 before calling this function.
429 struct dgrptabent
*ent
; /* Dev table entry structure */
430 struct member
*q
, *r
; /* Tmps for member structs */
431 char *record
; /* Record just read */
432 char *p
; /* Tmp char ptr */
433 int done
; /* TRUE if built an entry */
436 /* Open the device-group table if it's not already open */
438 if (!_opendgrptab("r"))
442 /* Get space for the structure we're returning */
443 if (!(ent
= malloc(sizeof (struct dgrptabent
)))) {
448 while (!done
&& (record
= getnextrec())) {
450 /* Is this a comment record or a data record */
451 if (strchr("#\n", *record
) ||
452 isspace((unsigned char)*record
)) {
455 * Record is a comment record
458 ent
->entryno
= recnum
++;
460 /* Alloc space for the comment and save pointer in struct */
461 if (ent
->dataspace
= malloc(strlen(record
)+1)) {
462 (void) strcpy(ent
->dataspace
, record
);
472 * Record is a data record
474 ent
->comment
= FALSE
;
476 /* Extract the device-group name */
477 if (p
= getfld(record
, ":")) {
479 /* Record is a proper record */
481 ent
->entryno
= recnum
++;
483 /* Copy device group name into malloc()ed space */
484 if (!(ent
->name
= malloc(strlen(p
)+1))) {
489 (void) strcpy(ent
->name
, p
);
492 * Extract the membership from the membership list
495 /* Get the 1st member */
496 ent
->dataspace
= NULL
;
497 while (((p
= getfld(NULL
, ",\n")) != NULL
) && !(*p
))
500 if (!(q
= malloc(sizeof (struct member
)))) {
506 if (!(q
->name
= malloc(strlen(p
)+1))) {
512 (void) strcpy(q
->name
, p
);
516 /* Get the rest of the members */
517 while (p
= getfld(NULL
, ",\n"))
519 if (!(r
= malloc(sizeof (struct member
)))) {
520 for (q
= ent
->membership
; q
; q
= r
) {
529 if (!(r
->name
= malloc(strlen(p
)+1))) {
531 for (q
= ent
->membership
; q
; q
= r
) {
542 (void) strcpy(r
->name
, p
);
549 ent
->membership
= NULL
;
552 } /* record contains a group name */
554 } /* record is a data record */
556 } /* while (!done && there's more records) */
559 /* An entry read? If not, free alloc'd space and return NULL */
570 * void _freedgrptabent(dgrptabent)
571 * struct dgrptabent *dgrptabent;
573 * This function frees space allocated to a device table entry.
576 * struct dgrptabent *dgrptabent The structure whose space is to be
583 _freedgrptabent(struct dgrptabent
*ent
) /* Structure to free */
589 struct member
*p
; /* Structure being freed */
590 struct member
*q
; /* Next structure to free */
593 * Free the space allocated to the membership structure.
597 if ((q
= ent
->membership
) != NULL
) do {
600 if (p
->name
) free(p
->name
);
604 /* Free the device group name */
605 if (ent
->name
) free(ent
->name
);
608 /* Free the membership string */
609 if (ent
->dataspace
) free(ent
->dataspace
);
613 * struct dgrptabent *_getdgrprec(dgroup)
616 * Thie _getdgrprec() function returns a pointer to a structure that
617 * contains the information in the device-group table entry that describes
618 * the device-group <dgroup>.
621 * char *dgroup A character-string describing the device-group whose
622 * record is to be retrieved from the device-group table.
624 * Returns: struct dgrptabent *
625 * A pointer to a structure describing the device group.
629 _getdgrprec(char *dgroup
) /* dgroup to search for */
635 struct dgrptabent
*dgrprec
; /* Pointer to current record */
636 int found
; /* FLAG, TRUE if found */
640 * Search the device-group table looking for the requested
647 while (!found
&& (dgrprec
= _getdgrptabent())) {
648 if (!dgrprec
->comment
&& strcmp(dgroup
, dgrprec
->name
) == 0)
650 else _freedgrptabent(dgrprec
);
653 /* Set up return codes if we've failed */
655 if (errno
== 0) errno
= EINVAL
;