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 /* 23 * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 31 #pragma ident "%Z%%M% %I% %E% SMI" 32 33 /* 34 * getdev.c 35 * 36 * Contains 37 * getdev Writes on the standard output stream a list of devices 38 * that match certain criteria. 39 */ 40 #include <sys/types.h> 41 #include <stdio.h> 42 #include <errno.h> 43 #include <stdlib.h> 44 #include <string.h> 45 #include <fmtmsg.h> 46 #include <devmgmt.h> 47 #include <devtab.h> 48 49 50 /* 51 * Local Definitions 52 * TRUE Boolean TRUE value 53 * FALSE Boolean FALSE value 54 * EX_OK Exit Value if all went well 55 * EX_ERROR Exit Value if an error occurred 56 * EX_DEVTAB Exit Value if the device table couldn't be opened 57 58 */ 59 60 #ifndef TRUE 61 #define TRUE (1) 62 #endif 63 64 #ifndef FALSE 65 #define FALSE (0) 66 #endif 67 68 #define EX_OK 0 69 #define EX_ERROR 1 70 #define EX_DEVTAB 2 71 72 73 /* 74 * Messages: 75 * M_USAGE Usage error 76 * M_DEVTAB Can't open the device table 77 * M_NODEV Device not found in the device table 78 * M_ERROR Unexpected or internal error 79 */ 80 81 #define M_USAGE "usage: getdev [-ae] [criterion [...]] [device [...]]" 82 #define M_DEVTAB "Cannot open the device table: %s" 83 #define M_NODEV "Device not found in the device table: %s" 84 #define M_ERROR "Internal error, errno=%d" 85 86 87 /* 88 * Local (Static) Definitions and macros 89 * buildcriterialist() Builds the criteria list from the command-line 90 * builddevlist() Builds the device list from the command-line 91 * lbl Buffer for the standard message label 92 * txt Buffer for the standard message text 93 * stdmsg(r,l,s,t) Write a standard message: 94 * r Recoverability flag 95 * l Standard label 96 * s Severity 97 * t Text 98 */ 99 100 static char **buildcriterialist(); 101 static char **builddevlist(); 102 103 static char lbl[MM_MXLABELLN+1]; 104 static char txt[MM_MXTXTLN+1]; 105 106 #define stdmsg(r,l,s,t) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,t,MM_NULLACT,MM_NULLTAG) 107 108 /* 109 * getdev [-ae] [criterion [...]] [device [...]] 110 * 111 * This command generates a list of devices that match the 112 * specified criteria. 113 * 114 * Options: 115 * -a A device must meet all of the criteria to be 116 * included in the generated list instead of just 117 * one of the criteria (the "and" flag) 118 * -e Exclude the devices mentioned from the generated 119 * list. If this flag is omitted, the devices in the 120 * list are selected from the devices mentioned. 121 * 122 * Arguments: 123 * criterion An <attr><op><value> expression that describes 124 * a device attribute. 125 * <attr> is a device attribute 126 * <op> may be = != : !: indicating equals, does not 127 * equal, is defined, and is not defined 128 * respectively 129 * <value> is the attribute value. Currently, the only 130 * value supported for the : and !: operators 131 * is * 132 * device A device to select for or exclude from the generated 133 * list 134 * 135 * Exit values: 136 * EX_OK All went well 137 * EX_ERROR An error (syntax, internal, or resource) occurred 138 * EX_DEVTAB The device-table could not be opened for reading 139 */ 140 141 main(argc, argv) 142 int argc; /* Number of items on the command line */ 143 char **argv; /* List of pointers to the arguments */ 144 { 145 146 /* 147 * Automatic data 148 */ 149 150 char **arglist; /* List of arguments */ 151 char **criterialist; /* List of criteria */ 152 char **devicelist; /* List of devices to search/ignore */ 153 char **fitdevlist; /* List of devices that fit criteria */ 154 char *cmdname; /* Simple command name */ 155 char *device; /* Device name in the list */ 156 char *devtab; /* The device table name */ 157 int exitcode; /* Value to return to the caller */ 158 int sev; /* Message severity */ 159 int optchar; /* Option character (from getopt()) */ 160 int andflag; /* TRUE if criteria are to be anded */ 161 int excludeflag; /* TRUE if exclude "devices" lists */ 162 int options; /* Options to pass to getdev() */ 163 int usageerr; /* TRUE if syntax error */ 164 165 166 /* Build the message label from the (simple) command name */ 167 if ((cmdname = strrchr(argv[0], '/')) != (char *) NULL) cmdname++; 168 else cmdname = argv[0]; 169 (void) strlcat(strcpy(lbl, "UX:"), cmdname, sizeof(lbl)); 170 171 /* Write text-component of messages only (goes away in SVR4.1) */ 172 (void) putenv("MSGVERB=text"); 173 174 /* 175 * Parse the command line: 176 * - Options 177 * - Selection criteria 178 * - Devices to include or exclude 179 */ 180 181 /* 182 * Extract options from the command line 183 */ 184 185 /* Initializations */ 186 andflag = FALSE; /* No -a -- Or criteria data */ 187 excludeflag = FALSE; /* No -e -- Include only mentioned devices */ 188 usageerr = FALSE; /* No errors on the command line (yet) */ 189 190 /* 191 * Loop until all of the command line options have been parced 192 */ 193 opterr = FALSE; /* Don't let getopt() write messages */ 194 while ((optchar = getopt(argc, argv, "ae")) != EOF) switch (optchar) { 195 196 /* -a List devices that fit all of the criteria listed */ 197 case 'a': 198 if (andflag) usageerr = TRUE; 199 else andflag = TRUE; 200 break; 201 202 /* -e Exclude those devices mentioned on the command line */ 203 case 'e': 204 if (excludeflag) usageerr = TRUE; 205 else excludeflag = TRUE; 206 break; 207 208 /* Default case -- command usage error */ 209 case '?': 210 default: 211 usageerr = TRUE; 212 break; 213 } 214 215 /* If there is a usage error, write an appropriate message and exit */ 216 if (usageerr) { 217 stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE); 218 exit(EX_ERROR); 219 } 220 221 /* Open the device file (if there's one to be opened) */ 222 if (!_opendevtab("r")) { 223 if (devtab = _devtabpath()) { 224 (void) snprintf(txt, sizeof(txt), M_DEVTAB, devtab); 225 sev = MM_ERROR; 226 exitcode = EX_DEVTAB; 227 } else { 228 (void) sprintf(txt, M_ERROR, errno); 229 sev = MM_HALT; 230 exitcode = EX_ERROR; 231 } 232 stdmsg(MM_NRECOV, lbl, sev, txt); 233 exit(exitcode); 234 } 235 236 /* Build the list of criteria and devices */ 237 arglist = argv + optind; 238 criterialist = buildcriterialist(arglist); 239 devicelist = builddevlist(arglist); 240 options = (excludeflag?DTAB_EXCLUDEFLAG:0)|(andflag?DTAB_ANDCRITERIA:0); 241 242 /* 243 * Get the list of devices that meets the criteria requested. If we 244 * got a list (that might be empty), write that list to the standard 245 * output file (stdout). 246 */ 247 248 exitcode = 0; 249 if (!(fitdevlist = getdev(devicelist, criterialist, options))) { 250 exitcode = 1; 251 } 252 else for (device = *fitdevlist++ ; device ; device = *fitdevlist++) 253 (void) puts(device); 254 255 /* Finished */ 256 return(exitcode); 257 } 258 259 /* 260 * char **buildcriterialist(arglist) 261 * char **arglist 262 * 263 * Build a list of pointers to the criterion on the command-line 264 * 265 * Arguments: 266 * arglist The list of arguments on the command-line 267 * 268 * Returns: char ** 269 * The address of the first item of the list of criterion on the 270 * command-line. This is a pointer to malloc()ed space. 271 */ 272 273 static char ** 274 buildcriterialist(arglist) 275 char **arglist; /* Pointer to the list of argument pointers */ 276 { 277 /* 278 * Automatic data 279 */ 280 281 char **pp; /* Pointer to a criteria */ 282 char **allocbuf; /* Pointer to the allocated data */ 283 int ncriteria; /* Number of criteria found */ 284 285 286 /* 287 * Search the argument list, looking for the end of the list or 288 * the first thing that's not a criteria. (A criteria is a 289 * character-string that contains a colon (':') or an equal-sign ('=') 290 */ 291 292 pp = arglist; 293 ncriteria = 0; 294 while (*pp && (strchr(*pp, '=') || strchr(*pp, ':'))) { 295 ncriteria++; 296 pp++; 297 } 298 299 if (ncriteria > 0) { 300 301 /* Allocate space for the list of criteria pointers */ 302 allocbuf = (char **) malloc((ncriteria+1)*sizeof(char **)); 303 304 /* 305 * Build the list of criteria arguments 306 */ 307 pp = allocbuf; /* Beginning of the list */ 308 while (*arglist && /* If there's more to do ... */ 309 (strchr(*arglist, '=') || /* and it's a = criterion ... */ 310 strchr(*arglist, ':'))) /* or it's a : criterion ... */ 311 *pp++ = *arglist++; /* Include it in the list */ 312 *pp = (char *) NULL; /* Terminate the list */ 313 314 } else allocbuf = (char **) NULL; /* NO criteria */ 315 316 317 return (allocbuf); 318 } 319 320 /* 321 * char **builddevlist(arglist) 322 * char **arglist 323 * 324 * Builds a list of pointers to the devices mentioned on the command- 325 * line and returns the address of that list. 326 * 327 * Arguments: 328 * arglist The address of the list of arguments to the 329 * getdev command. 330 * 331 * Returns: char ** 332 * A pointer to the first item in the list of pointers to devices 333 * specified on the command-line 334 */ 335 336 static char ** 337 builddevlist(arglist) 338 char **arglist; /* Pointer to the list of pointers to args */ 339 { 340 /* 341 * Automatic data 342 */ 343 344 /* 345 * Search the argument list, looking for the end of the list or the 346 * first thing that's not a criteria. It is the first device in the 347 * list of devices (if any). 348 */ 349 350 while (*arglist && (strchr(*arglist, '=') || strchr(*arglist, ':'))) arglist++; 351 352 /* Return a pointer to the argument list. */ 353 return(*arglist?arglist:(char **) NULL); 354 } 355