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 /*LINTLIBRARY*/ 32 33 /* 34 * getdgrp.c 35 * 36 * Contains the following global functions: 37 * getdgrp() Get the device groups that meet certain criteria. 38 */ 39 40 /* 41 * Header Files Referenced 42 * <sys/types.h> Data Types 43 * <stdio.h> Standard I/O definitions 44 * <string.h> Character-string definitions 45 * <devmgmt.h> Definitions for accessing device table files 46 * "devtab.h" Local definitions for device tables 47 */ 48 49 #include <sys/types.h> 50 #include <stdio.h> 51 #include <string.h> 52 #include <stdlib.h> 53 #include <devmgmt.h> 54 #include "devtab.h" 55 56 /* 57 * Local definitions 58 * struct dgrplist Structure that makes up the internal device 59 * group list 60 * Members: 61 * name Name of the device group 62 * next Pointer to the next in the list 63 */ 64 65 struct dgrplist { 66 char *name; 67 struct dgrplist *next; 68 }; 69 70 71 /* 72 * Local functions 73 * initdgrplist Initialize the internal device group list 74 * addtodgrplist Add a device group to the device group list 75 * isindevlist Does the device group contain a device? 76 * isincallerslist Is a device group in the caller's list? 77 * buildreturnlist Build list of device groups to return 78 * freedgrplist Free the internal device group list 79 */ 80 81 static void initdgrplist(void); 82 static int addtodgrplist(struct dgrptabent *); 83 static int isindevlist(struct dgrptabent *, char **); 84 static int isincallerslist(struct dgrptabent *, char **); 85 static char **buildreturnlist(void); 86 static void freedgrplist(void); 87 88 89 /* 90 * Local data 91 * dgrplistfirst First (dummy) node in the device group list 92 * dgrplistcount Number of items in the device group list 93 */ 94 95 static struct dgrplist dgrplistfirst; 96 static int dgrplistcount; 97 98 /* 99 * char **getdgrp(dgroups, criteria, options) 100 * char **dgroups 101 * char **criteria 102 * int options 103 * 104 * This function compiles a list of device groups containing devices 105 * that meet certain criteria and returns a pointer to the first 106 * item in that list. 107 * 108 * Arguments: 109 * dgroups The list of device groups to choose from or the list 110 * of device groups to exclude from the list (depends on 111 * "options" 112 * criteria The criteria that a device must meet 113 * options Indicates 1) whether to "and" the criteria or to "or" 114 * the criteria, 2) indicates whether to limit the 115 * generated list to "dgroups" or to exclude those 116 * device-groups from the list, 3) to list all device 117 * groups even if they don't contain valid devices. 118 * 119 * Returns: char ** 120 * A pointer to the first address in the list of addresses of generated 121 * device groups 122 */ 123 124 char ** 125 getdgrp( 126 char **dgroups, /* List of device groups */ 127 char **criteria, /* List of criteria to meet */ 128 int options) /* Options governing the search */ 129 { 130 /* Automatic data */ 131 char **devlist; /* Devices that meet criteria */ 132 char **plist; /* Device groups to return */ 133 struct dgrptabent *dgrp; /* Dgrp information struct */ 134 int errorflag; /* TRUE if error occurred */ 135 int listallflag; /* TRUE if DTAB_LISTALL && (!criteria || !*criteria) */ 136 137 138 /* 139 * Open the device-group table if needed 140 */ 141 142 if (!oam_dgroup && !_opendgrptab("r")) 143 return (NULL); 144 145 146 /* 147 * Get the list of devices that meet the criteria specified 148 * This step can be skipped if DTAB_LISTALL is requested and 149 * there is no criteria list. 150 */ 151 152 if (((options & DTAB_LISTALL) == 0) || (criteria && *criteria)) { 153 devlist = getdev(NULL, criteria, (options & DTAB_ANDCRITERIA)); 154 listallflag = FALSE; 155 } else { 156 devlist = NULL; 157 listallflag = TRUE; 158 } 159 160 161 /* 162 * Initialize the device group list (contains the device groups 163 * we're accumulating) 164 */ 165 166 errorflag = FALSE; 167 initdgrplist(); 168 169 170 /* 171 * If no device groups were specified by the caller, accumulate all 172 * device groups 173 */ 174 175 _setdgrptab(); 176 if (!dgroups || !(*dgroups)) { 177 while (!errorflag && (dgrp = _getdgrptabent())) { 178 if (!dgrp->comment && (listallflag || 179 isindevlist(dgrp, devlist))) 180 errorflag = !addtodgrplist(dgrp); 181 _freedgrptabent(dgrp); 182 } 183 } 184 185 else { 186 187 /* 188 * If the exclusion flag is not set, build a list of device 189 * groups that is a subset of those specified by the caller 190 */ 191 192 if ((options & DTAB_EXCLUDEFLAG) == 0) { 193 while (!errorflag && (dgrp = _getdgrptabent())) { 194 if (!dgrp->comment && isincallerslist(dgrp, dgroups) && 195 (listallflag || isindevlist(dgrp, devlist))) { 196 errorflag = !addtodgrplist(dgrp); 197 } 198 _freedgrptabent(dgrp); 199 } 200 } 201 202 /* 203 * If the exclusion flag is set, build a list of device groups 204 * that meet the criteria and are not in the list of device 205 * groups specified by the caller. 206 */ 207 else { 208 while (!errorflag && (dgrp = _getdgrptabent())) { 209 if (!dgrp->comment && !isincallerslist(dgrp, dgroups) && 210 (listallflag || isindevlist(dgrp, devlist))) { 211 errorflag = !addtodgrplist(dgrp); 212 } 213 _freedgrptabent(dgrp); 214 } 215 } 216 } 217 plist = buildreturnlist(); 218 freedgrplist(); 219 _enddgrptab(); 220 return (plist); 221 } 222 223 /* 224 * int initdgrplist() 225 * 226 * Initializes the internal device group linked list 227 * 228 * Arguments: None 229 * 230 * Returns: void 231 */ 232 233 static void 234 initdgrplist(void) 235 { 236 /* Automatic data */ 237 238 /* 239 * Initialize the structure. Dummy node points to nothing, count to 240 * zero. 241 */ 242 dgrplistcount = 0; 243 dgrplistfirst.name = ""; 244 dgrplistfirst.next = NULL; 245 } 246 247 /* 248 * int addtodgrplist(dgrp) 249 * struct dgrptabent *dgrp 250 * 251 * Adds the device group described by the "dgrp" structure to the 252 * internal list of device-groups we're accumulating. 253 * 254 * Arguments: 255 * dgrp Describes the device-group we're adding 256 * 257 * Returns: int 258 * TRUE if successful, FALSE otherwise 259 */ 260 261 static int 262 addtodgrplist(struct dgrptabent *dgrp) 263 { 264 /* Automatic data */ 265 struct dgrplist *newnode; /* Allocated node */ 266 struct dgrplist *p; /* Running dgrp list ptr */ 267 struct dgrplist *q; /* Another Running dgrp list ptr */ 268 char *newstr; /* Space for the dgroup name */ 269 int errorflag; /* TRUE if error */ 270 int cmpval; /* Value from strcmp() */ 271 272 /* No errors seen yet */ 273 errorflag = FALSE; 274 275 /* Find where we're supposed to insert this item in the list */ 276 q = &dgrplistfirst; 277 p = q->next; 278 while (p && ((cmpval = strcmp(p->name, dgrp->name)) < 0)) { 279 q = p; 280 p = p->next; 281 } 282 283 /* If the item isn't already in the list, insert it */ 284 if ((p == NULL) || (cmpval != 0)) { 285 286 /* Allocate space for the structure */ 287 newnode = malloc(sizeof (struct dgrplist)); 288 if (newnode) { 289 290 /* Allocate space for the device group name */ 291 if (newstr = malloc(strlen(dgrp->name)+1)) { 292 293 /* Link the new structure into the list */ 294 newnode->name = strcpy(newstr, dgrp->name); 295 newnode->next = p; 296 q->next = newnode; 297 dgrplistcount++; 298 } else { 299 /* No space for the string. Clean up */ 300 errorflag = TRUE; 301 free(newnode); 302 } 303 } else errorflag = TRUE; 304 } 305 306 /* Return a value that indicates whether we've had an error */ 307 return (!errorflag); 308 } 309 310 /* 311 * int isindevlist(dgrp, devlist) 312 * struct dgrptabent *dgrp 313 * char **devlist 314 * 315 * This function searches the device membership list of the device 316 * group <dgrp> for any of the devices listed in the list of devices 317 * <devlist>. It returns TRUE if at least one device in <devlist> is 318 * found in <dgrp>, otherwise it returns false. 319 * 320 * Arguments: 321 * dgrp The device group to examine 322 * devlist The list of devices to search for 323 * 324 * Returns: int 325 * TRUE if one of the devices in <devlist> is a member of the device 326 * group <dgrp>, FALSE otherwise 327 */ 328 329 static int 330 isindevlist( 331 struct dgrptabent *dgrp, /* Dgrp to search for */ 332 char **devlist) /* List of devices to search against */ 333 { 334 /* Automatic data */ 335 struct member *pmbr; /* Next member of the dgrp list */ 336 char **pdev; /* Next device in the dev list */ 337 char *mbralias; /* The alias of a group member */ 338 int cmpval; /* strcmp() result */ 339 int notfound; /* TRUE if no mbr of dgrp is in dev list */ 340 int allocflag; /* TRUE if the mbralias string is malloc()ed */ 341 342 343 /* 344 * For each device in the device group, search the alphabetically 345 * sorted list of devices for that device. 346 */ 347 348 notfound = TRUE; 349 for (pmbr = dgrp->membership; notfound && pmbr; pmbr = pmbr->next) { 350 351 /* 352 * Get the member's alias (we've got it if the member is not a 353 * pathname) 354 */ 355 allocflag = (*pmbr->name == '/'); 356 if (allocflag) 357 mbralias = devattr(pmbr->name, DTAB_ALIAS); 358 else mbralias = pmbr->name; 359 360 /* If we've got a member alias, search the device list for it */ 361 if (mbralias) 362 for (pdev = devlist; notfound && *pdev; pdev++) 363 364 if ((cmpval = strcmp(mbralias, *pdev)) == 0) notfound = FALSE; 365 else if (cmpval < 0) 366 break; /* Optimization: alpha sorted list */ 367 368 /* 369 * Free the space allocated to the member alias 370 * (if it was allocated above by devattr()) 371 */ 372 if (allocflag) free(mbralias); 373 374 } 375 376 377 /* 378 * Return a value indicating that we the device group contains 379 * a member that is in the list of devices 380 */ 381 382 return (!notfound); 383 } 384 385 /* 386 * int isincallerslist(dgrp, dgroups) 387 * struct dgrptabent *dgrp 388 * char **dgroups 389 * 390 * This function looks through the "dgroups" list for the device 391 * group described by "dgrp" 392 * 393 * Arguments: 394 * dgrp Device group to search for 395 * dgroups The address of the first item in the list of device 396 * groups to search 397 * 398 * Returns: int 399 * TRUE if found, FALSE otherwise 400 */ 401 402 static int 403 isincallerslist( 404 struct dgrptabent *dgrp, /* Dgrp to search for */ 405 char **dgroups) /* Caller's list of dgroups */ 406 { 407 /* Automatic data */ 408 char **pdgrp; 409 int notfound; 410 411 /* 412 * Search the list of device groups for the name of the device group 413 * in the structure described by <dgrp>. 414 */ 415 416 /* Initializations */ 417 notfound = TRUE; 418 419 /* Search the device group list for name of this device group */ 420 for (pdgrp = dgroups; notfound && *pdgrp; pdgrp++) { 421 if (strcmp(dgrp->name, *pdgrp) == 0) notfound = FALSE; 422 } 423 424 /* Return TRUE if the device group is in the list, FALSE otherwise */ 425 return (!notfound); 426 } 427 428 /* 429 * char **buildreturnlist() 430 * 431 * This function builds the list of pointers to device groups 432 * to return to the caller from the linked list of device-groups 433 * we've been accumulating. 434 * 435 * Arguments: none 436 * 437 * Returns: char ** 438 * A pointer to the first element in the malloc()ed list of pointers 439 * to malloc()ed character strings containing device groups which have 440 * member devices which match the criteria 441 */ 442 443 static char ** 444 buildreturnlist(void) 445 { 446 char **list; /* List being built */ 447 char **pp; /* Temp ptr within list */ 448 struct dgrplist *pdgrpent; /* Ptr into list of dgrps to return */ 449 450 /* Allocate space for the list of pointers to device groups */ 451 list = malloc((dgrplistcount+1)*sizeof (char *)); 452 453 /* 454 * For each item in the device group list, put an entry in the 455 * list of names we're building 456 */ 457 if ((pp = list) != NULL) { 458 for (pdgrpent = dgrplistfirst.next; pdgrpent; 459 pdgrpent = pdgrpent->next) { 460 461 *pp++ = pdgrpent->name; 462 } 463 /* The list ends with a null pointer */ 464 *pp = NULL; 465 } 466 467 /* Return a pointer to the allocated list */ 468 return (list); 469 } 470 471 /* 472 * void freedgrplist() 473 * 474 * This function frees the resources allocated to the internal 475 * linked list of device groups 476 * 477 * Arguments: none 478 * 479 * Returns: void 480 */ 481 482 static void 483 freedgrplist(void) 484 { 485 struct dgrplist *pdgrpent; /* Dgrp to free */ 486 struct dgrplist *nextnode; /* Next one to free */ 487 488 for (pdgrpent = dgrplistfirst.next; pdgrpent; pdgrpent = nextnode) { 489 nextnode = pdgrpent->next; 490 free(pdgrpent); 491 } 492 } 493