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