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