1 /* 2 * CDDL HEADER START 3 * 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. 8 * 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. 13 * 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] 19 * 20 * CDDL HEADER END 21 */ 22 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 23 /* All Rights Reserved */ 24 25 26 /* 27 * Copyright (c) 1997, by Sun Microsystems, Inc. 28 * All rights reserved. 29 */ 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /*LINTLIBRARY*/ 34 35 /* 36 * getdgrp.c 37 * 38 * Contains the following global functions: 39 * getdgrp() Get the device groups that meet certain criteria. 40 */ 41 42 /* 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 49 */ 50 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" 57 58 /* 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 65 */ 66 67 struct dgrplist { 68 char *name; 69 struct dgrplist *next; 70 }; 71 72 73 /* 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 81 */ 82 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); 89 90 91 /* 92 * Local data 93 * dgrplistfirst First (dummy) node in the device group list 94 * dgrplistcount Number of items in the device group list 95 */ 96 97 static struct dgrplist dgrplistfirst; 98 static int dgrplistcount; 99 100 /* 101 * char **getdgrp(dgroups, criteria, options) 102 * char **dgroups 103 * char **criteria 104 * int options 105 * 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. 109 * 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. 120 * 121 * Returns: char ** 122 * A pointer to the first address in the list of addresses of generated 123 * device groups 124 */ 125 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 */ 131 { 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) */ 138 139 140 /* 141 * Open the device-group table if needed 142 */ 143 144 if (!oam_dgroup && !_opendgrptab("r")) 145 return (NULL); 146 147 148 /* 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. 152 */ 153 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; 160 } 161 162 163 /* 164 * Initialize the device group list (contains the device groups 165 * we're accumulating) 166 */ 167 168 errorflag = FALSE; 169 initdgrplist(); 170 171 172 /* 173 * If no device groups were specified by the caller, accumulate all 174 * device groups 175 */ 176 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); 184 } 185 } 186 187 else { 188 189 /* 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 192 */ 193 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); 199 } 200 _freedgrptabent(dgrp); 201 } 202 } 203 204 /* 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. 208 */ 209 else { 210 while (!errorflag && (dgrp = _getdgrptabent())) { 211 if (!dgrp->comment && !isincallerslist(dgrp, dgroups) && 212 (listallflag || isindevlist(dgrp, devlist))) { 213 errorflag = !addtodgrplist(dgrp); 214 } 215 _freedgrptabent(dgrp); 216 } 217 } 218 } 219 plist = buildreturnlist(); 220 freedgrplist(); 221 _enddgrptab(); 222 return (plist); 223 } 224 225 /* 226 * int initdgrplist() 227 * 228 * Initializes the internal device group linked list 229 * 230 * Arguments: None 231 * 232 * Returns: void 233 */ 234 235 static void 236 initdgrplist(void) 237 { 238 /* Automatic data */ 239 240 /* 241 * Initialize the structure. Dummy node points to nothing, count to 242 * zero. 243 */ 244 dgrplistcount = 0; 245 dgrplistfirst.name = ""; 246 dgrplistfirst.next = NULL; 247 } 248 249 /* 250 * int addtodgrplist(dgrp) 251 * struct dgrptabent *dgrp 252 * 253 * Adds the device group described by the "dgrp" structure to the 254 * internal list of device-groups we're accumulating. 255 * 256 * Arguments: 257 * dgrp Describes the device-group we're adding 258 * 259 * Returns: int 260 * TRUE if successful, FALSE otherwise 261 */ 262 263 static int 264 addtodgrplist(struct dgrptabent *dgrp) 265 { 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() */ 273 274 /* No errors seen yet */ 275 errorflag = FALSE; 276 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; 283 } 284 285 /* If the item isn't already in the list, insert it */ 286 if ((p == NULL) || (cmpval != 0)) { 287 288 /* Allocate space for the structure */ 289 newnode = malloc(sizeof (struct dgrplist)); 290 if (newnode) { 291 292 /* Allocate space for the device group name */ 293 if (newstr = malloc(strlen(dgrp->name)+1)) { 294 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); 304 } 305 } else errorflag = TRUE; 306 } 307 308 /* Return a value that indicates whether we've had an error */ 309 return (!errorflag); 310 } 311 312 /* 313 * int isindevlist(dgrp, devlist) 314 * struct dgrptabent *dgrp 315 * char **devlist 316 * 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. 321 * 322 * Arguments: 323 * dgrp The device group to examine 324 * devlist The list of devices to search for 325 * 326 * Returns: int 327 * TRUE if one of the devices in <devlist> is a member of the device 328 * group <dgrp>, FALSE otherwise 329 */ 330 331 static int 332 isindevlist( 333 struct dgrptabent *dgrp, /* Dgrp to search for */ 334 char **devlist) /* List of devices to search against */ 335 { 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 */ 343 344 345 /* 346 * For each device in the device group, search the alphabetically 347 * sorted list of devices for that device. 348 */ 349 350 notfound = TRUE; 351 for (pmbr = dgrp->membership; notfound && pmbr; pmbr = pmbr->next) { 352 353 /* 354 * Get the member's alias (we've got it if the member is not a 355 * pathname) 356 */ 357 allocflag = (*pmbr->name == '/'); 358 if (allocflag) 359 mbralias = devattr(pmbr->name, DTAB_ALIAS); 360 else mbralias = pmbr->name; 361 362 /* If we've got a member alias, search the device list for it */ 363 if (mbralias) 364 for (pdev = devlist; notfound && *pdev; pdev++) 365 366 if ((cmpval = strcmp(mbralias, *pdev)) == 0) notfound = FALSE; 367 else if (cmpval < 0) 368 break; /* Optimization: alpha sorted list */ 369 370 /* 371 * Free the space allocated to the member alias 372 * (if it was allocated above by devattr()) 373 */ 374 if (allocflag) free(mbralias); 375 376 } 377 378 379 /* 380 * Return a value indicating that we the device group contains 381 * a member that is in the list of devices 382 */ 383 384 return (!notfound); 385 } 386 387 /* 388 * int isincallerslist(dgrp, dgroups) 389 * struct dgrptabent *dgrp 390 * char **dgroups 391 * 392 * This function looks through the "dgroups" list for the device 393 * group described by "dgrp" 394 * 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 399 * 400 * Returns: int 401 * TRUE if found, FALSE otherwise 402 */ 403 404 static int 405 isincallerslist( 406 struct dgrptabent *dgrp, /* Dgrp to search for */ 407 char **dgroups) /* Caller's list of dgroups */ 408 { 409 /* Automatic data */ 410 char **pdgrp; 411 int notfound; 412 413 /* 414 * Search the list of device groups for the name of the device group 415 * in the structure described by <dgrp>. 416 */ 417 418 /* Initializations */ 419 notfound = TRUE; 420 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; 424 } 425 426 /* Return TRUE if the device group is in the list, FALSE otherwise */ 427 return (!notfound); 428 } 429 430 /* 431 * char **buildreturnlist() 432 * 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. 436 * 437 * Arguments: none 438 * 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 443 */ 444 445 static char ** 446 buildreturnlist(void) 447 { 448 char **list; /* List being built */ 449 char **pp; /* Temp ptr within list */ 450 struct dgrplist *pdgrpent; /* Ptr into list of dgrps to return */ 451 452 /* Allocate space for the list of pointers to device groups */ 453 list = malloc((dgrplistcount+1)*sizeof (char *)); 454 455 /* 456 * For each item in the device group list, put an entry in the 457 * list of names we're building 458 */ 459 if ((pp = list) != NULL) { 460 for (pdgrpent = dgrplistfirst.next; pdgrpent; 461 pdgrpent = pdgrpent->next) { 462 463 *pp++ = pdgrpent->name; 464 } 465 /* The list ends with a null pointer */ 466 *pp = NULL; 467 } 468 469 /* Return a pointer to the allocated list */ 470 return (list); 471 } 472 473 /* 474 * void freedgrplist() 475 * 476 * This function frees the resources allocated to the internal 477 * linked list of device groups 478 * 479 * Arguments: none 480 * 481 * Returns: void 482 */ 483 484 static void 485 freedgrplist(void) 486 { 487 struct dgrplist *pdgrpent; /* Dgrp to free */ 488 struct dgrplist *nextnode; /* Next one to free */ 489 490 for (pdgrpent = dgrplistfirst.next; pdgrpent; pdgrpent = nextnode) { 491 nextnode = pdgrpent->next; 492 free(pdgrpent); 493 } 494 } 495