Merge commit 'cc543d0f9e35a75cc302a4cb152756d233299564'
[unleashed.git] / usr / src / lib / libadm / common / getdgrp.c
blob3b5eb89da0374acb5a6bdd503d3776ee73328a62
1 /*
2 * CDDL HEADER START
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
7 * with the License.
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]
20 * CDDL HEADER END
22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
23 /* All Rights Reserved */
27 * Copyright (c) 1997, by Sun Microsystems, Inc.
28 * All rights reserved.
31 #pragma ident "%Z%%M% %I% %E% SMI"
33 /*LINTLIBRARY*/
36 * getdgrp.c
38 * Contains the following global functions:
39 * getdgrp() Get the device groups that meet certain criteria.
43 * Header Files Referenced
44 * <sys/types.h> Data Types
45 * <stdio.h> Standard I/O definitions
46 * <string.h> Character-string definitions
47 * <devmgmt.h> Definitions for accessing device table files
48 * "devtab.h" Local definitions for device tables
51 #include <sys/types.h>
52 #include <stdio.h>
53 #include <string.h>
54 #include <stdlib.h>
55 #include <devmgmt.h>
56 #include "devtab.h"
59 * Local definitions
60 * struct dgrplist Structure that makes up the internal device
61 * group list
62 * Members:
63 * name Name of the device group
64 * next Pointer to the next in the list
67 struct dgrplist {
68 char *name;
69 struct dgrplist *next;
74 * Local functions
75 * initdgrplist Initialize the internal device group list
76 * addtodgrplist Add a device group to the device group list
77 * isindevlist Does the device group contain a device?
78 * isincallerslist Is a device group in the caller's list?
79 * buildreturnlist Build list of device groups to return
80 * freedgrplist Free the internal device group list
83 static void initdgrplist(void);
84 static int addtodgrplist(struct dgrptabent *);
85 static int isindevlist(struct dgrptabent *, char **);
86 static int isincallerslist(struct dgrptabent *, char **);
87 static char **buildreturnlist(void);
88 static void freedgrplist(void);
92 * Local data
93 * dgrplistfirst First (dummy) node in the device group list
94 * dgrplistcount Number of items in the device group list
97 static struct dgrplist dgrplistfirst;
98 static int dgrplistcount;
101 * char **getdgrp(dgroups, criteria, options)
102 * char **dgroups
103 * char **criteria
104 * int options
106 * This function compiles a list of device groups containing devices
107 * that meet certain criteria and returns a pointer to the first
108 * item in that list.
110 * Arguments:
111 * dgroups The list of device groups to choose from or the list
112 * of device groups to exclude from the list (depends on
113 * "options"
114 * criteria The criteria that a device must meet
115 * options Indicates 1) whether to "and" the criteria or to "or"
116 * the criteria, 2) indicates whether to limit the
117 * generated list to "dgroups" or to exclude those
118 * device-groups from the list, 3) to list all device
119 * groups even if they don't contain valid devices.
121 * Returns: char **
122 * A pointer to the first address in the list of addresses of generated
123 * device groups
126 char **
127 getdgrp(
128 char **dgroups, /* List of device groups */
129 char **criteria, /* List of criteria to meet */
130 int options) /* Options governing the search */
132 /* Automatic data */
133 char **devlist; /* Devices that meet criteria */
134 char **plist; /* Device groups to return */
135 struct dgrptabent *dgrp; /* Dgrp information struct */
136 int errorflag; /* TRUE if error occurred */
137 int listallflag; /* TRUE if DTAB_LISTALL && (!criteria || !*criteria) */
141 * Open the device-group table if needed
144 if (!oam_dgroup && !_opendgrptab("r"))
145 return (NULL);
149 * Get the list of devices that meet the criteria specified
150 * This step can be skipped if DTAB_LISTALL is requested and
151 * there is no criteria list.
154 if (((options & DTAB_LISTALL) == 0) || (criteria && *criteria)) {
155 devlist = getdev(NULL, criteria, (options & DTAB_ANDCRITERIA));
156 listallflag = FALSE;
157 } else {
158 devlist = NULL;
159 listallflag = TRUE;
164 * Initialize the device group list (contains the device groups
165 * we're accumulating)
168 errorflag = FALSE;
169 initdgrplist();
173 * If no device groups were specified by the caller, accumulate all
174 * device groups
177 _setdgrptab();
178 if (!dgroups || !(*dgroups)) {
179 while (!errorflag && (dgrp = _getdgrptabent())) {
180 if (!dgrp->comment && (listallflag ||
181 isindevlist(dgrp, devlist)))
182 errorflag = !addtodgrplist(dgrp);
183 _freedgrptabent(dgrp);
187 else {
190 * If the exclusion flag is not set, build a list of device
191 * groups that is a subset of those specified by the caller
194 if ((options & DTAB_EXCLUDEFLAG) == 0) {
195 while (!errorflag && (dgrp = _getdgrptabent())) {
196 if (!dgrp->comment && isincallerslist(dgrp, dgroups) &&
197 (listallflag || isindevlist(dgrp, devlist))) {
198 errorflag = !addtodgrplist(dgrp);
200 _freedgrptabent(dgrp);
205 * If the exclusion flag is set, build a list of device groups
206 * that meet the criteria and are not in the list of device
207 * groups specified by the caller.
209 else {
210 while (!errorflag && (dgrp = _getdgrptabent())) {
211 if (!dgrp->comment && !isincallerslist(dgrp, dgroups) &&
212 (listallflag || isindevlist(dgrp, devlist))) {
213 errorflag = !addtodgrplist(dgrp);
215 _freedgrptabent(dgrp);
219 plist = buildreturnlist();
220 freedgrplist();
221 _enddgrptab();
222 return (plist);
226 * int initdgrplist()
228 * Initializes the internal device group linked list
230 * Arguments: None
232 * Returns: void
235 static void
236 initdgrplist(void)
238 /* Automatic data */
241 * Initialize the structure. Dummy node points to nothing, count to
242 * zero.
244 dgrplistcount = 0;
245 dgrplistfirst.name = "";
246 dgrplistfirst.next = NULL;
250 * int addtodgrplist(dgrp)
251 * struct dgrptabent *dgrp
253 * Adds the device group described by the "dgrp" structure to the
254 * internal list of device-groups we're accumulating.
256 * Arguments:
257 * dgrp Describes the device-group we're adding
259 * Returns: int
260 * TRUE if successful, FALSE otherwise
263 static int
264 addtodgrplist(struct dgrptabent *dgrp)
266 /* Automatic data */
267 struct dgrplist *newnode; /* Allocated node */
268 struct dgrplist *p; /* Running dgrp list ptr */
269 struct dgrplist *q; /* Another Running dgrp list ptr */
270 char *newstr; /* Space for the dgroup name */
271 int errorflag; /* TRUE if error */
272 int cmpval; /* Value from strcmp() */
274 /* No errors seen yet */
275 errorflag = FALSE;
277 /* Find where we're supposed to insert this item in the list */
278 q = &dgrplistfirst;
279 p = q->next;
280 while (p && ((cmpval = strcmp(p->name, dgrp->name)) < 0)) {
281 q = p;
282 p = p->next;
285 /* If the item isn't already in the list, insert it */
286 if ((p == NULL) || (cmpval != 0)) {
288 /* Allocate space for the structure */
289 newnode = malloc(sizeof (struct dgrplist));
290 if (newnode) {
292 /* Allocate space for the device group name */
293 if (newstr = malloc(strlen(dgrp->name)+1)) {
295 /* Link the new structure into the list */
296 newnode->name = strcpy(newstr, dgrp->name);
297 newnode->next = p;
298 q->next = newnode;
299 dgrplistcount++;
300 } else {
301 /* No space for the string. Clean up */
302 errorflag = TRUE;
303 free(newnode);
305 } else errorflag = TRUE;
308 /* Return a value that indicates whether we've had an error */
309 return (!errorflag);
313 * int isindevlist(dgrp, devlist)
314 * struct dgrptabent *dgrp
315 * char **devlist
317 * This function searches the device membership list of the device
318 * group <dgrp> for any of the devices listed in the list of devices
319 * <devlist>. It returns TRUE if at least one device in <devlist> is
320 * found in <dgrp>, otherwise it returns false.
322 * Arguments:
323 * dgrp The device group to examine
324 * devlist The list of devices to search for
326 * Returns: int
327 * TRUE if one of the devices in <devlist> is a member of the device
328 * group <dgrp>, FALSE otherwise
331 static int
332 isindevlist(
333 struct dgrptabent *dgrp, /* Dgrp to search for */
334 char **devlist) /* List of devices to search against */
336 /* Automatic data */
337 struct member *pmbr; /* Next member of the dgrp list */
338 char **pdev; /* Next device in the dev list */
339 char *mbralias; /* The alias of a group member */
340 int cmpval; /* strcmp() result */
341 int notfound; /* TRUE if no mbr of dgrp is in dev list */
342 int allocflag; /* TRUE if the mbralias string is malloc()ed */
346 * For each device in the device group, search the alphabetically
347 * sorted list of devices for that device.
350 notfound = TRUE;
351 for (pmbr = dgrp->membership; notfound && pmbr; pmbr = pmbr->next) {
354 * Get the member's alias (we've got it if the member is not a
355 * pathname)
357 allocflag = (*pmbr->name == '/');
358 if (allocflag)
359 mbralias = devattr(pmbr->name, DTAB_ALIAS);
360 else mbralias = pmbr->name;
362 /* If we've got a member alias, search the device list for it */
363 if (mbralias)
364 for (pdev = devlist; notfound && *pdev; pdev++)
366 if ((cmpval = strcmp(mbralias, *pdev)) == 0) notfound = FALSE;
367 else if (cmpval < 0)
368 break; /* Optimization: alpha sorted list */
371 * Free the space allocated to the member alias
372 * (if it was allocated above by devattr())
374 if (allocflag) free(mbralias);
380 * Return a value indicating that we the device group contains
381 * a member that is in the list of devices
384 return (!notfound);
388 * int isincallerslist(dgrp, dgroups)
389 * struct dgrptabent *dgrp
390 * char **dgroups
392 * This function looks through the "dgroups" list for the device
393 * group described by "dgrp"
395 * Arguments:
396 * dgrp Device group to search for
397 * dgroups The address of the first item in the list of device
398 * groups to search
400 * Returns: int
401 * TRUE if found, FALSE otherwise
404 static int
405 isincallerslist(
406 struct dgrptabent *dgrp, /* Dgrp to search for */
407 char **dgroups) /* Caller's list of dgroups */
409 /* Automatic data */
410 char **pdgrp;
411 int notfound;
414 * Search the list of device groups for the name of the device group
415 * in the structure described by <dgrp>.
418 /* Initializations */
419 notfound = TRUE;
421 /* Search the device group list for name of this device group */
422 for (pdgrp = dgroups; notfound && *pdgrp; pdgrp++) {
423 if (strcmp(dgrp->name, *pdgrp) == 0) notfound = FALSE;
426 /* Return TRUE if the device group is in the list, FALSE otherwise */
427 return (!notfound);
431 * char **buildreturnlist()
433 * This function builds the list of pointers to device groups
434 * to return to the caller from the linked list of device-groups
435 * we've been accumulating.
437 * Arguments: none
439 * Returns: char **
440 * A pointer to the first element in the malloc()ed list of pointers
441 * to malloc()ed character strings containing device groups which have
442 * member devices which match the criteria
445 static char **
446 buildreturnlist(void)
448 char **list; /* List being built */
449 char **pp; /* Temp ptr within list */
450 struct dgrplist *pdgrpent; /* Ptr into list of dgrps to return */
452 /* Allocate space for the list of pointers to device groups */
453 list = malloc((dgrplistcount+1)*sizeof (char *));
456 * For each item in the device group list, put an entry in the
457 * list of names we're building
459 if ((pp = list) != NULL) {
460 for (pdgrpent = dgrplistfirst.next; pdgrpent;
461 pdgrpent = pdgrpent->next) {
463 *pp++ = pdgrpent->name;
465 /* The list ends with a null pointer */
466 *pp = NULL;
469 /* Return a pointer to the allocated list */
470 return (list);
474 * void freedgrplist()
476 * This function frees the resources allocated to the internal
477 * linked list of device groups
479 * Arguments: none
481 * Returns: void
484 static void
485 freedgrplist(void)
487 struct dgrplist *pdgrpent; /* Dgrp to free */
488 struct dgrplist *nextnode; /* Next one to free */
490 for (pdgrpent = dgrplistfirst.next; pdgrpent; pdgrpent = nextnode) {
491 nextnode = pdgrpent->next;
492 free(pdgrpent);