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 #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 int
main(int argc,char * argv[])161 main(int argc, char *argv[])
162 {
163
164 /* Automatic data */
165 char *cmdname; /* Pointer to command name */
166 char *device; /* Pointer to device name */
167 char *attr; /* Pointer to current attribute */
168 char *value; /* Pointer to current attr value */
169 char *p; /* Temporary character pointer */
170 char **argptr; /* Pointer into argv[] list */
171 int syntaxerr; /* TRUE if invalid option seen */
172 int noerr; /* TRUE if all's well in processing */
173 int v_seen; /* TRUE if -v is on the command-line */
174 int exitcode; /* Value to return */
175 int severity; /* Message severity */
176 int c; /* Temp char value */
177
178
179 /*
180 * Parse the command-line.
181 */
182
183 syntaxerr = FALSE;
184 v_seen = FALSE;
185
186 /* Extract options */
187 opterr = FALSE;
188 while ((c = getopt(argc, argv, "v")) != EOF) switch(c) {
189
190 /* -v option: No argument, may be seen only once */
191 case 'v':
192 if (!v_seen) v_seen = TRUE;
193 else syntaxerr = TRUE;
194 break;
195
196 /* Unknown option */
197 default:
198 syntaxerr = TRUE;
199 break;
200 }
201
202 /* Build the command name */
203 cmdname = argv[0];
204 if ((p = strrchr(cmdname, '/')) != (char *) NULL) cmdname = p+1;
205 (void) strlcat(strcpy(lbl, "UX:"), cmdname, sizeof(lbl));
206
207 /* Make only the text-component of messages appear (remove this in SVR4.1) */
208 (void) putenv("MSGVERB=text");
209
210 /*
211 * Check for a usage error
212 * - invalid option
213 * - arg count < 2
214 * - arg count < 3 && -v used
215 */
216
217 if (syntaxerr || (argc < (optind+1))) {
218 stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE);
219 exit(EX_ERROR);
220 }
221
222 /* Open the device file (if there's one to be opened) */
223 if (!_opendevtab("r")) {
224 if (p = _devtabpath()) {
225 (void) snprintf(txt, sizeof(txt), M_DEVTAB, p);
226 exitcode = EX_DEVTAB;
227 severity = MM_ERROR;
228 } else {
229 (void) sprintf(txt, M_ERROR, errno);
230 exitcode = EX_ERROR;
231 severity = MM_HALT;
232 }
233 stdmsg(MM_NRECOV, lbl, severity, txt);
234 exit(exitcode);
235 }
236
237
238 /*
239 * Get the list of known attributes for the device. This does
240 * two things. First, it verifies that the device is known in the
241 * device table. Second, it gets the attributes to list just in
242 * case no attributes were specified. Then, set a pointer to the
243 * list of attributes to be extracted and listed...
244 */
245
246 device = argv[optind];
247 if ((argptr = listdev(device)) == (char **) NULL) {
248 if (errno == ENODEV) {
249 (void) snprintf(txt, sizeof(txt), M_NODEV, device);
250 exitcode = EX_NODEV;
251 severity = MM_ERROR;
252 } else {
253 (void) sprintf(txt, M_ERROR, errno);
254 exitcode = EX_ERROR;
255 severity = MM_HALT;
256 }
257 stdmsg(MM_NRECOV, lbl, severity, txt);
258 exit(exitcode);
259 }
260 if (argc > (optind+1)) argptr = &argv[optind+1];
261
262
263 /*
264 * List attributes. If a requested attribute is not defined,
265 * list the value of that attribute as null. (Using shell
266 * variables as the model for this.)
267 */
268
269 exitcode = EX_OK;
270 noerr = TRUE;
271 while (noerr && ((attr = *argptr++) != (char *) NULL)) {
272 if (!(value = devattr(device, attr))) {
273 if (errno == EINVAL) {
274 value = "";
275 (void) snprintf(txt, sizeof(txt), M_NOATTR, attr);
276 /* stdmsg(MM_RECOVER, lbl, MM_WARNING, txt); */
277 exitcode = EX_NOATTR;
278 } else {
279 noerr = FALSE;
280 (void) sprintf(txt, M_ERROR, errno);
281 stdmsg(MM_NRECOV, lbl, MM_ERROR, txt);
282 exitcode = EX_ERROR;
283 }
284 }
285 if (noerr && v_seen) {
286 (void) fputs(attr, stdout);
287 (void) fputs("='", stdout);
288 for (p = value ; *p ; p++) {
289 (void) putc(*p, stdout);
290 if (*p == '\'') (void) fputs("\"'\"'", stdout);
291 }
292 (void) fputs("'\n", stdout);
293 } else if (noerr) {
294 (void) fputs(value, stdout);
295 (void) putc('\n', stdout);
296 }
297 }
298
299 return (exitcode);
300 }
301