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 #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 int 142 main(int argc, char **argv) 143 { 144 145 /* 146 * Automatic data 147 */ 148 149 char **arglist; /* List of arguments */ 150 char **criterialist; /* List of criteria */ 151 char **devicelist; /* List of devices to search/ignore */ 152 char **fitdevlist; /* List of devices that fit criteria */ 153 char *cmdname; /* Simple command name */ 154 char *device; /* Device name in the list */ 155 char *devtab; /* The device table name */ 156 int exitcode; /* Value to return to the caller */ 157 int sev; /* Message severity */ 158 int optchar; /* Option character (from getopt()) */ 159 int andflag; /* TRUE if criteria are to be anded */ 160 int excludeflag; /* TRUE if exclude "devices" lists */ 161 int options; /* Options to pass to getdev() */ 162 int usageerr; /* TRUE if syntax error */ 163 164 165 /* Build the message label from the (simple) command name */ 166 if ((cmdname = strrchr(argv[0], '/')) != (char *) NULL) cmdname++; 167 else cmdname = argv[0]; 168 (void) strlcat(strcpy(lbl, "UX:"), cmdname, sizeof(lbl)); 169 170 /* Write text-component of messages only (goes away in SVR4.1) */ 171 (void) putenv("MSGVERB=text"); 172 173 /* 174 * Parse the command line: 175 * - Options 176 * - Selection criteria 177 * - Devices to include or exclude 178 */ 179 180 /* 181 * Extract options from the command line 182 */ 183 184 /* Initializations */ 185 andflag = FALSE; /* No -a -- Or criteria data */ 186 excludeflag = FALSE; /* No -e -- Include only mentioned devices */ 187 usageerr = FALSE; /* No errors on the command line (yet) */ 188 189 /* 190 * Loop until all of the command line options have been parced 191 */ 192 opterr = FALSE; /* Don't let getopt() write messages */ 193 while ((optchar = getopt(argc, argv, "ae")) != EOF) switch (optchar) { 194 195 /* -a List devices that fit all of the criteria listed */ 196 case 'a': 197 if (andflag) usageerr = TRUE; 198 else andflag = TRUE; 199 break; 200 201 /* -e Exclude those devices mentioned on the command line */ 202 case 'e': 203 if (excludeflag) usageerr = TRUE; 204 else excludeflag = TRUE; 205 break; 206 207 /* Default case -- command usage error */ 208 case '?': 209 default: 210 usageerr = TRUE; 211 break; 212 } 213 214 /* If there is a usage error, write an appropriate message and exit */ 215 if (usageerr) { 216 stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE); 217 exit(EX_ERROR); 218 } 219 220 /* Open the device file (if there's one to be opened) */ 221 if (!_opendevtab("r")) { 222 if (devtab = _devtabpath()) { 223 (void) snprintf(txt, sizeof(txt), M_DEVTAB, devtab); 224 sev = MM_ERROR; 225 exitcode = EX_DEVTAB; 226 } else { 227 (void) sprintf(txt, M_ERROR, errno); 228 sev = MM_HALT; 229 exitcode = EX_ERROR; 230 } 231 stdmsg(MM_NRECOV, lbl, sev, txt); 232 exit(exitcode); 233 } 234 235 /* Build the list of criteria and devices */ 236 arglist = argv + optind; 237 criterialist = buildcriterialist(arglist); 238 devicelist = builddevlist(arglist); 239 options = (excludeflag?DTAB_EXCLUDEFLAG:0)|(andflag?DTAB_ANDCRITERIA:0); 240 241 /* 242 * Get the list of devices that meets the criteria requested. If we 243 * got a list (that might be empty), write that list to the standard 244 * output file (stdout). 245 */ 246 247 exitcode = 0; 248 if (!(fitdevlist = getdev(devicelist, criterialist, options))) { 249 exitcode = 1; 250 } 251 else for (device = *fitdevlist++ ; device ; device = *fitdevlist++) 252 (void) puts(device); 253 254 /* Finished */ 255 return(exitcode); 256 } 257 258 /* 259 * char **buildcriterialist(arglist) 260 * char **arglist 261 * 262 * Build a list of pointers to the criterion on the command-line 263 * 264 * Arguments: 265 * arglist The list of arguments on the command-line 266 * 267 * Returns: char ** 268 * The address of the first item of the list of criterion on the 269 * command-line. This is a pointer to malloc()ed space. 270 */ 271 272 static char ** 273 buildcriterialist(arglist) 274 char **arglist; /* Pointer to the list of argument pointers */ 275 { 276 /* 277 * Automatic data 278 */ 279 280 char **pp; /* Pointer to a criteria */ 281 char **allocbuf; /* Pointer to the allocated data */ 282 int ncriteria; /* Number of criteria found */ 283 284 285 /* 286 * Search the argument list, looking for the end of the list or 287 * the first thing that's not a criteria. (A criteria is a 288 * character-string that contains a colon (':') or an equal-sign ('=') 289 */ 290 291 pp = arglist; 292 ncriteria = 0; 293 while (*pp && (strchr(*pp, '=') || strchr(*pp, ':'))) { 294 ncriteria++; 295 pp++; 296 } 297 298 if (ncriteria > 0) { 299 300 /* Allocate space for the list of criteria pointers */ 301 allocbuf = (char **) malloc((ncriteria+1)*sizeof(char **)); 302 303 /* 304 * Build the list of criteria arguments 305 */ 306 pp = allocbuf; /* Beginning of the list */ 307 while (*arglist && /* If there's more to do ... */ 308 (strchr(*arglist, '=') || /* and it's a = criterion ... */ 309 strchr(*arglist, ':'))) /* or it's a : criterion ... */ 310 *pp++ = *arglist++; /* Include it in the list */ 311 *pp = (char *) NULL; /* Terminate the list */ 312 313 } else allocbuf = (char **) NULL; /* NO criteria */ 314 315 316 return (allocbuf); 317 } 318 319 /* 320 * char **builddevlist(arglist) 321 * char **arglist 322 * 323 * Builds a list of pointers to the devices mentioned on the command- 324 * line and returns the address of that list. 325 * 326 * Arguments: 327 * arglist The address of the list of arguments to the 328 * getdev command. 329 * 330 * Returns: char ** 331 * A pointer to the first item in the list of pointers to devices 332 * specified on the command-line 333 */ 334 335 static char ** 336 builddevlist(arglist) 337 char **arglist; /* Pointer to the list of pointers to args */ 338 { 339 /* 340 * Automatic data 341 */ 342 343 /* 344 * Search the argument list, looking for the end of the list or the 345 * first thing that's not a criteria. It is the first device in the 346 * list of devices (if any). 347 */ 348 349 while (*arglist && (strchr(*arglist, '=') || strchr(*arglist, ':'))) arglist++; 350 351 /* Return a pointer to the argument list. */ 352 return(*arglist?arglist:(char **) NULL); 353 } 354