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