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