1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2002-2003 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28*7c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 29*7c478bd9Sstevel@tonic-gate 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate /* 34*7c478bd9Sstevel@tonic-gate * devattr.c 35*7c478bd9Sstevel@tonic-gate * 36*7c478bd9Sstevel@tonic-gate * Contains the following: 37*7c478bd9Sstevel@tonic-gate * devattr Command that returns [specific] attributes for 38*7c478bd9Sstevel@tonic-gate * a device. 39*7c478bd9Sstevel@tonic-gate */ 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate /* 42*7c478bd9Sstevel@tonic-gate * devattr [-v] device [attr [...]] 43*7c478bd9Sstevel@tonic-gate * 44*7c478bd9Sstevel@tonic-gate * This command searches the device table file for the device specified. 45*7c478bd9Sstevel@tonic-gate * If it finds the device (matched either by alias or major and minor 46*7c478bd9Sstevel@tonic-gate * device number), it extracts the attribute(s) specified and writes 47*7c478bd9Sstevel@tonic-gate * that value to the standard output stream (stdout). 48*7c478bd9Sstevel@tonic-gate * 49*7c478bd9Sstevel@tonic-gate * The command writes the values of the attributes to stdout one per 50*7c478bd9Sstevel@tonic-gate * line, in the order that they were requested. If the -v option is 51*7c478bd9Sstevel@tonic-gate * requested, it writes the attributes in the form <attr>='<value>' where 52*7c478bd9Sstevel@tonic-gate * <attr> is the name of the attribute and <value> is the value of that 53*7c478bd9Sstevel@tonic-gate * attribute. 54*7c478bd9Sstevel@tonic-gate * 55*7c478bd9Sstevel@tonic-gate * Returns: 56*7c478bd9Sstevel@tonic-gate * 0 The command succeeded 57*7c478bd9Sstevel@tonic-gate * 1 The command syntax is incorrect, 58*7c478bd9Sstevel@tonic-gate * An invalid option was used, 59*7c478bd9Sstevel@tonic-gate * An internal error occurred that prevented completion 60*7c478bd9Sstevel@tonic-gate * 2 The device table could not be opened for reading. 61*7c478bd9Sstevel@tonic-gate * 3 The requested device was not found in the device table 62*7c478bd9Sstevel@tonic-gate * 4 A requested attribute was not defined for the device 63*7c478bd9Sstevel@tonic-gate */ 64*7c478bd9Sstevel@tonic-gate 65*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 66*7c478bd9Sstevel@tonic-gate #include <stdio.h> 67*7c478bd9Sstevel@tonic-gate #include <string.h> 68*7c478bd9Sstevel@tonic-gate #include <errno.h> 69*7c478bd9Sstevel@tonic-gate #include <fmtmsg.h> 70*7c478bd9Sstevel@tonic-gate #include <devmgmt.h> 71*7c478bd9Sstevel@tonic-gate #include <devtab.h> 72*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 73*7c478bd9Sstevel@tonic-gate 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate /* 76*7c478bd9Sstevel@tonic-gate * Local constant definitions 77*7c478bd9Sstevel@tonic-gate * TRUE Boolean TRUE 78*7c478bd9Sstevel@tonic-gate * FALSE Boolean FALSE 79*7c478bd9Sstevel@tonic-gate */ 80*7c478bd9Sstevel@tonic-gate 81*7c478bd9Sstevel@tonic-gate #ifndef TRUE 82*7c478bd9Sstevel@tonic-gate #define TRUE 1 83*7c478bd9Sstevel@tonic-gate #endif 84*7c478bd9Sstevel@tonic-gate 85*7c478bd9Sstevel@tonic-gate #ifndef FALSE 86*7c478bd9Sstevel@tonic-gate #define FALSE 0 87*7c478bd9Sstevel@tonic-gate #endif 88*7c478bd9Sstevel@tonic-gate 89*7c478bd9Sstevel@tonic-gate /* 90*7c478bd9Sstevel@tonic-gate * Messages 91*7c478bd9Sstevel@tonic-gate * M_USAGE Usage error 92*7c478bd9Sstevel@tonic-gate * M_ERROR Unexpected internal error 93*7c478bd9Sstevel@tonic-gate * M_NODEV Device not found in the device table 94*7c478bd9Sstevel@tonic-gate * M_NOATTR Attribute not found 95*7c478bd9Sstevel@tonic-gate * M_DEVTAB Can't open the device table 96*7c478bd9Sstevel@tonic-gate */ 97*7c478bd9Sstevel@tonic-gate 98*7c478bd9Sstevel@tonic-gate #define M_USAGE "usage: devattr [-v] device [attribute [...]]" 99*7c478bd9Sstevel@tonic-gate #define M_ERROR "Internal error, errno=%d" 100*7c478bd9Sstevel@tonic-gate #define M_NODEV "Device not found in the device table: %s" 101*7c478bd9Sstevel@tonic-gate #define M_NOATTR "Attrubute not found: %s" 102*7c478bd9Sstevel@tonic-gate #define M_DEVTAB "Cannot open the device table: %s" 103*7c478bd9Sstevel@tonic-gate 104*7c478bd9Sstevel@tonic-gate 105*7c478bd9Sstevel@tonic-gate /* 106*7c478bd9Sstevel@tonic-gate * Exit codes: 107*7c478bd9Sstevel@tonic-gate * EX_OK All's well that ends well 108*7c478bd9Sstevel@tonic-gate * EX_ERROR Some problem caused termination 109*7c478bd9Sstevel@tonic-gate * EX_DEVTAB Device table could not be opened 110*7c478bd9Sstevel@tonic-gate * EX_NODEV The device wasn't found in the device table 111*7c478bd9Sstevel@tonic-gate * EX_NOATTR A requested attribute wasn't defined for the device 112*7c478bd9Sstevel@tonic-gate */ 113*7c478bd9Sstevel@tonic-gate 114*7c478bd9Sstevel@tonic-gate #define EX_OK 0 115*7c478bd9Sstevel@tonic-gate #define EX_ERROR 1 116*7c478bd9Sstevel@tonic-gate #define EX_DEVTAB 2 117*7c478bd9Sstevel@tonic-gate #define EX_NODEV 3 118*7c478bd9Sstevel@tonic-gate #define EX_NOATTR 4 119*7c478bd9Sstevel@tonic-gate 120*7c478bd9Sstevel@tonic-gate 121*7c478bd9Sstevel@tonic-gate /* 122*7c478bd9Sstevel@tonic-gate * Macros 123*7c478bd9Sstevel@tonic-gate * stdmsg(r,l,s,t) Standard Message Generator 124*7c478bd9Sstevel@tonic-gate * r Recoverability flag 125*7c478bd9Sstevel@tonic-gate * l Standard Label 126*7c478bd9Sstevel@tonic-gate * s Severity 127*7c478bd9Sstevel@tonic-gate * t Text 128*7c478bd9Sstevel@tonic-gate */ 129*7c478bd9Sstevel@tonic-gate 130*7c478bd9Sstevel@tonic-gate #define stdmsg(r,l,s,t) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,t,MM_NULLACT,MM_NULLTAG) 131*7c478bd9Sstevel@tonic-gate 132*7c478bd9Sstevel@tonic-gate 133*7c478bd9Sstevel@tonic-gate /* 134*7c478bd9Sstevel@tonic-gate * Local static data 135*7c478bd9Sstevel@tonic-gate * lbl Buffer for the command label (for messages) 136*7c478bd9Sstevel@tonic-gate * txt Buffer for the text of messages 137*7c478bd9Sstevel@tonic-gate */ 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate static char lbl[MM_MXLABELLN+1]; 140*7c478bd9Sstevel@tonic-gate static char txt[MM_MXTXTLN+1]; 141*7c478bd9Sstevel@tonic-gate 142*7c478bd9Sstevel@tonic-gate /* 143*7c478bd9Sstevel@tonic-gate * main() 144*7c478bd9Sstevel@tonic-gate * 145*7c478bd9Sstevel@tonic-gate * Implements the command "devattr". This function parses the command 146*7c478bd9Sstevel@tonic-gate * line, then calls the devattr() function looking for the specified 147*7c478bd9Sstevel@tonic-gate * device and the requested attribute. It writes the information to 148*7c478bd9Sstevel@tonic-gate * the standard output file in the requested format. 149*7c478bd9Sstevel@tonic-gate * 150*7c478bd9Sstevel@tonic-gate * Exits: 151*7c478bd9Sstevel@tonic-gate * 0 The command succeeded 152*7c478bd9Sstevel@tonic-gate * 1 The command syntax is incorrect, 153*7c478bd9Sstevel@tonic-gate * An invalid option was used, 154*7c478bd9Sstevel@tonic-gate * An internal error occurred that prevented completion 155*7c478bd9Sstevel@tonic-gate * 2 The device table could not be opened for reading. 156*7c478bd9Sstevel@tonic-gate * 3 The requested device was not found in the device table 157*7c478bd9Sstevel@tonic-gate * 4 A requested attribute was not defined for the device 158*7c478bd9Sstevel@tonic-gate */ 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate main(argc, argv) 161*7c478bd9Sstevel@tonic-gate int argc; /* Number of arguments */ 162*7c478bd9Sstevel@tonic-gate char *argv[]; /* Pointer to arguments */ 163*7c478bd9Sstevel@tonic-gate { 164*7c478bd9Sstevel@tonic-gate 165*7c478bd9Sstevel@tonic-gate /* Automatic data */ 166*7c478bd9Sstevel@tonic-gate char *cmdname; /* Pointer to command name */ 167*7c478bd9Sstevel@tonic-gate char *device; /* Pointer to device name */ 168*7c478bd9Sstevel@tonic-gate char *attr; /* Pointer to current attribute */ 169*7c478bd9Sstevel@tonic-gate char *value; /* Pointer to current attr value */ 170*7c478bd9Sstevel@tonic-gate char *p; /* Temporary character pointer */ 171*7c478bd9Sstevel@tonic-gate char **argptr; /* Pointer into argv[] list */ 172*7c478bd9Sstevel@tonic-gate int syntaxerr; /* TRUE if invalid option seen */ 173*7c478bd9Sstevel@tonic-gate int noerr; /* TRUE if all's well in processing */ 174*7c478bd9Sstevel@tonic-gate int v_seen; /* TRUE if -v is on the command-line */ 175*7c478bd9Sstevel@tonic-gate int exitcode; /* Value to return */ 176*7c478bd9Sstevel@tonic-gate int severity; /* Message severity */ 177*7c478bd9Sstevel@tonic-gate int c; /* Temp char value */ 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate 180*7c478bd9Sstevel@tonic-gate /* 181*7c478bd9Sstevel@tonic-gate * Parse the command-line. 182*7c478bd9Sstevel@tonic-gate */ 183*7c478bd9Sstevel@tonic-gate 184*7c478bd9Sstevel@tonic-gate syntaxerr = FALSE; 185*7c478bd9Sstevel@tonic-gate v_seen = FALSE; 186*7c478bd9Sstevel@tonic-gate 187*7c478bd9Sstevel@tonic-gate /* Extract options */ 188*7c478bd9Sstevel@tonic-gate opterr = FALSE; 189*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "v")) != EOF) switch(c) { 190*7c478bd9Sstevel@tonic-gate 191*7c478bd9Sstevel@tonic-gate /* -v option: No argument, may be seen only once */ 192*7c478bd9Sstevel@tonic-gate case 'v': 193*7c478bd9Sstevel@tonic-gate if (!v_seen) v_seen = TRUE; 194*7c478bd9Sstevel@tonic-gate else syntaxerr = TRUE; 195*7c478bd9Sstevel@tonic-gate break; 196*7c478bd9Sstevel@tonic-gate 197*7c478bd9Sstevel@tonic-gate /* Unknown option */ 198*7c478bd9Sstevel@tonic-gate default: 199*7c478bd9Sstevel@tonic-gate syntaxerr = TRUE; 200*7c478bd9Sstevel@tonic-gate break; 201*7c478bd9Sstevel@tonic-gate } 202*7c478bd9Sstevel@tonic-gate 203*7c478bd9Sstevel@tonic-gate /* Build the command name */ 204*7c478bd9Sstevel@tonic-gate cmdname = argv[0]; 205*7c478bd9Sstevel@tonic-gate if ((p = strrchr(cmdname, '/')) != (char *) NULL) cmdname = p+1; 206*7c478bd9Sstevel@tonic-gate (void) strlcat(strcpy(lbl, "UX:"), cmdname, sizeof(lbl)); 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* Make only the text-component of messages appear (remove this in SVR4.1) */ 209*7c478bd9Sstevel@tonic-gate (void) putenv("MSGVERB=text"); 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate /* 212*7c478bd9Sstevel@tonic-gate * Check for a usage error 213*7c478bd9Sstevel@tonic-gate * - invalid option 214*7c478bd9Sstevel@tonic-gate * - arg count < 2 215*7c478bd9Sstevel@tonic-gate * - arg count < 3 && -v used 216*7c478bd9Sstevel@tonic-gate */ 217*7c478bd9Sstevel@tonic-gate 218*7c478bd9Sstevel@tonic-gate if (syntaxerr || (argc < (optind+1))) { 219*7c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE); 220*7c478bd9Sstevel@tonic-gate exit(EX_ERROR); 221*7c478bd9Sstevel@tonic-gate } 222*7c478bd9Sstevel@tonic-gate 223*7c478bd9Sstevel@tonic-gate /* Open the device file (if there's one to be opened) */ 224*7c478bd9Sstevel@tonic-gate if (!_opendevtab("r")) { 225*7c478bd9Sstevel@tonic-gate if (p = _devtabpath()) { 226*7c478bd9Sstevel@tonic-gate (void) snprintf(txt, sizeof(txt), M_DEVTAB, p); 227*7c478bd9Sstevel@tonic-gate exitcode = EX_DEVTAB; 228*7c478bd9Sstevel@tonic-gate severity = MM_ERROR; 229*7c478bd9Sstevel@tonic-gate } else { 230*7c478bd9Sstevel@tonic-gate (void) sprintf(txt, M_ERROR, errno); 231*7c478bd9Sstevel@tonic-gate exitcode = EX_ERROR; 232*7c478bd9Sstevel@tonic-gate severity = MM_HALT; 233*7c478bd9Sstevel@tonic-gate } 234*7c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, severity, txt); 235*7c478bd9Sstevel@tonic-gate exit(exitcode); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate 239*7c478bd9Sstevel@tonic-gate /* 240*7c478bd9Sstevel@tonic-gate * Get the list of known attributes for the device. This does 241*7c478bd9Sstevel@tonic-gate * two things. First, it verifies that the device is known in the 242*7c478bd9Sstevel@tonic-gate * device table. Second, it gets the attributes to list just in 243*7c478bd9Sstevel@tonic-gate * case no attributes were specified. Then, set a pointer to the 244*7c478bd9Sstevel@tonic-gate * list of attributes to be extracted and listed... 245*7c478bd9Sstevel@tonic-gate */ 246*7c478bd9Sstevel@tonic-gate 247*7c478bd9Sstevel@tonic-gate device = argv[optind]; 248*7c478bd9Sstevel@tonic-gate if ((argptr = listdev(device)) == (char **) NULL) { 249*7c478bd9Sstevel@tonic-gate if (errno == ENODEV) { 250*7c478bd9Sstevel@tonic-gate (void) snprintf(txt, sizeof(txt), M_NODEV, device); 251*7c478bd9Sstevel@tonic-gate exitcode = EX_NODEV; 252*7c478bd9Sstevel@tonic-gate severity = MM_ERROR; 253*7c478bd9Sstevel@tonic-gate } else { 254*7c478bd9Sstevel@tonic-gate (void) sprintf(txt, M_ERROR, errno); 255*7c478bd9Sstevel@tonic-gate exitcode = EX_ERROR; 256*7c478bd9Sstevel@tonic-gate severity = MM_HALT; 257*7c478bd9Sstevel@tonic-gate } 258*7c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, severity, txt); 259*7c478bd9Sstevel@tonic-gate exit(exitcode); 260*7c478bd9Sstevel@tonic-gate } 261*7c478bd9Sstevel@tonic-gate if (argc > (optind+1)) argptr = &argv[optind+1]; 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate 264*7c478bd9Sstevel@tonic-gate /* 265*7c478bd9Sstevel@tonic-gate * List attributes. If a requested attribute is not defined, 266*7c478bd9Sstevel@tonic-gate * list the value of that attribute as null. (Using shell 267*7c478bd9Sstevel@tonic-gate * variables as the model for this.) 268*7c478bd9Sstevel@tonic-gate */ 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate exitcode = EX_OK; 271*7c478bd9Sstevel@tonic-gate noerr = TRUE; 272*7c478bd9Sstevel@tonic-gate while (noerr && ((attr = *argptr++) != (char *) NULL)) { 273*7c478bd9Sstevel@tonic-gate if (!(value = devattr(device, attr))) { 274*7c478bd9Sstevel@tonic-gate if (errno == EINVAL) { 275*7c478bd9Sstevel@tonic-gate value = ""; 276*7c478bd9Sstevel@tonic-gate (void) snprintf(txt, sizeof(txt), M_NOATTR, attr); 277*7c478bd9Sstevel@tonic-gate /* stdmsg(MM_RECOVER, lbl, MM_WARNING, txt); */ 278*7c478bd9Sstevel@tonic-gate exitcode = EX_NOATTR; 279*7c478bd9Sstevel@tonic-gate } else { 280*7c478bd9Sstevel@tonic-gate noerr = FALSE; 281*7c478bd9Sstevel@tonic-gate (void) sprintf(txt, M_ERROR, errno); 282*7c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, txt); 283*7c478bd9Sstevel@tonic-gate exitcode = EX_ERROR; 284*7c478bd9Sstevel@tonic-gate } 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate if (noerr && v_seen) { 287*7c478bd9Sstevel@tonic-gate (void) fputs(attr, stdout); 288*7c478bd9Sstevel@tonic-gate (void) fputs("='", stdout); 289*7c478bd9Sstevel@tonic-gate for (p = value ; *p ; p++) { 290*7c478bd9Sstevel@tonic-gate (void) putc(*p, stdout); 291*7c478bd9Sstevel@tonic-gate if (*p == '\'') (void) fputs("\"'\"'", stdout); 292*7c478bd9Sstevel@tonic-gate } 293*7c478bd9Sstevel@tonic-gate (void) fputs("'\n", stdout); 294*7c478bd9Sstevel@tonic-gate } else if (noerr) { 295*7c478bd9Sstevel@tonic-gate (void) fputs(value, stdout); 296*7c478bd9Sstevel@tonic-gate (void) putc('\n', stdout); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate } 299*7c478bd9Sstevel@tonic-gate 300*7c478bd9Sstevel@tonic-gate return (exitcode); 301*7c478bd9Sstevel@tonic-gate } 302