/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* devattr.c
*
* Contains the following:
* devattr Command that returns [specific] attributes for
* a device.
*/
/*
* devattr [-v] device [attr [...]]
*
* This command searches the device table file for the device specified.
* If it finds the device (matched either by alias or major and minor
* device number), it extracts the attribute(s) specified and writes
* that value to the standard output stream (stdout).
*
* The command writes the values of the attributes to stdout one per
* line, in the order that they were requested. If the -v option is
* requested, it writes the attributes in the form <attr>='<value>' where
* <attr> is the name of the attribute and <value> is the value of that
* attribute.
*
* Returns:
* 0 The command succeeded
* 1 The command syntax is incorrect,
* An invalid option was used,
* An internal error occurred that prevented completion
* 2 The device table could not be opened for reading.
* 3 The requested device was not found in the device table
* 4 A requested attribute was not defined for the device
*/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <fmtmsg.h>
#include <devmgmt.h>
#include <devtab.h>
#include <stdlib.h>
/*
* Local constant definitions
* TRUE Boolean TRUE
* FALSE Boolean FALSE
*/
#ifndef TRUE
#define TRUE 1
#endif
#ifndef FALSE
#define FALSE 0
#endif
/*
* Messages
* M_USAGE Usage error
* M_ERROR Unexpected internal error
* M_NODEV Device not found in the device table
* M_NOATTR Attribute not found
* M_DEVTAB Can't open the device table
*/
#define M_USAGE "usage: devattr [-v] device [attribute [...]]"
#define M_ERROR "Internal error, errno=%d"
#define M_NODEV "Device not found in the device table: %s"
#define M_NOATTR "Attrubute not found: %s"
#define M_DEVTAB "Cannot open the device table: %s"
/*
* Exit codes:
* EX_OK All's well that ends well
* EX_ERROR Some problem caused termination
* EX_DEVTAB Device table could not be opened
* EX_NODEV The device wasn't found in the device table
* EX_NOATTR A requested attribute wasn't defined for the device
*/
#define EX_OK 0
#define EX_ERROR 1
#define EX_DEVTAB 2
#define EX_NODEV 3
#define EX_NOATTR 4
/*
* Macros
* stdmsg(r,l,s,t) Standard Message Generator
* r Recoverability flag
* l Standard Label
* s Severity
* t Text
*/
#define stdmsg(r,l,s,t) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,t,MM_NULLACT,MM_NULLTAG)
/*
* Local static data
* lbl Buffer for the command label (for messages)
* txt Buffer for the text of messages
*/
static char lbl[MM_MXLABELLN+1];
static char txt[MM_MXTXTLN+1];
/*
* main()
*
* Implements the command "devattr". This function parses the command
* line, then calls the devattr() function looking for the specified
* device and the requested attribute. It writes the information to
* the standard output file in the requested format.
*
* Exits:
* 0 The command succeeded
* 1 The command syntax is incorrect,
* An invalid option was used,
* An internal error occurred that prevented completion
* 2 The device table could not be opened for reading.
* 3 The requested device was not found in the device table
* 4 A requested attribute was not defined for the device
*/
int
main(int argc, char *argv[])
{
/* Automatic data */
char *cmdname; /* Pointer to command name */
char *device; /* Pointer to device name */
char *attr; /* Pointer to current attribute */
char *value; /* Pointer to current attr value */
char *p; /* Temporary character pointer */
char **argptr; /* Pointer into argv[] list */
int syntaxerr; /* TRUE if invalid option seen */
int noerr; /* TRUE if all's well in processing */
int v_seen; /* TRUE if -v is on the command-line */
int exitcode; /* Value to return */
int severity; /* Message severity */
int c; /* Temp char value */
/*
* Parse the command-line.
*/
syntaxerr = FALSE;
v_seen = FALSE;
/* Extract options */
opterr = FALSE;
while ((c = getopt(argc, argv, "v")) != EOF) switch(c) {
/* -v option: No argument, may be seen only once */
case 'v':
if (!v_seen) v_seen = TRUE;
else syntaxerr = TRUE;
break;
/* Unknown option */
default:
syntaxerr = TRUE;
break;
}
/* Build the command name */
cmdname = argv[0];
if ((p = strrchr(cmdname, '/')) != (char *) NULL) cmdname = p+1;
(void) strlcat(strcpy(lbl, "UX:"), cmdname, sizeof(lbl));
/* Make only the text-component of messages appear (remove this in SVR4.1) */
(void) putenv("MSGVERB=text");
/*
* Check for a usage error
* - invalid option
* - arg count < 2
* - arg count < 3 && -v used
*/
if (syntaxerr || (argc < (optind+1))) {
stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE);
exit(EX_ERROR);
}
/* Open the device file (if there's one to be opened) */
if (!_opendevtab("r")) {
if (p = _devtabpath()) {
(void) snprintf(txt, sizeof(txt), M_DEVTAB, p);
exitcode = EX_DEVTAB;
severity = MM_ERROR;
} else {
(void) sprintf(txt, M_ERROR, errno);
exitcode = EX_ERROR;
severity = MM_HALT;
}
stdmsg(MM_NRECOV, lbl, severity, txt);
exit(exitcode);
}
/*
* Get the list of known attributes for the device. This does
* two things. First, it verifies that the device is known in the
* device table. Second, it gets the attributes to list just in
* case no attributes were specified. Then, set a pointer to the
* list of attributes to be extracted and listed...
*/
device = argv[optind];
if ((argptr = listdev(device)) == (char **) NULL) {
if (errno == ENODEV) {
(void) snprintf(txt, sizeof(txt), M_NODEV, device);
exitcode = EX_NODEV;
severity = MM_ERROR;
} else {
(void) sprintf(txt, M_ERROR, errno);
exitcode = EX_ERROR;
severity = MM_HALT;
}
stdmsg(MM_NRECOV, lbl, severity, txt);
exit(exitcode);
}
if (argc > (optind+1)) argptr = &argv[optind+1];
/*
* List attributes. If a requested attribute is not defined,
* list the value of that attribute as null. (Using shell
* variables as the model for this.)
*/
exitcode = EX_OK;
noerr = TRUE;
while (noerr && ((attr = *argptr++) != (char *) NULL)) {
if (!(value = devattr(device, attr))) {
if (errno == EINVAL) {
value = "";
(void) snprintf(txt, sizeof(txt), M_NOATTR, attr);
/* stdmsg(MM_RECOVER, lbl, MM_WARNING, txt); */
exitcode = EX_NOATTR;
} else {
noerr = FALSE;
(void) sprintf(txt, M_ERROR, errno);
stdmsg(MM_NRECOV, lbl, MM_ERROR, txt);
exitcode = EX_ERROR;
}
}
if (noerr && v_seen) {
(void) fputs(attr, stdout);
(void) fputs("='", stdout);
for (p = value ; *p ; p++) {
(void) putc(*p, stdout);
if (*p == '\'') (void) fputs("\"'\"'", stdout);
}
(void) fputs("'\n", stdout);
} else if (noerr) {
(void) fputs(value, stdout);
(void) putc('\n', stdout);
}
}
return (exitcode);
}