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 * devfree key [device [...]]
35 */
36
37 #include <sys/types.h>
38 #include <sys/param.h>
39 #include <stdio.h>
40 #include <errno.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <fmtmsg.h>
44 #include <devmgmt.h>
45 #include <values.h>
46 #include <devtab.h>
47
48
49 /*
50 * Local definitions
51 * TRUE Boolean TRUE value
52 * FALSE Boolean FALSE value
53 */
54 #ifndef TRUE
55 #define TRUE ('t')
56 #endif
57
58 #ifndef FALSE
59 #define FALSE 0
60 #endif
61
62
63 /*
64 * Exit codes:
65 * EX_OK Exit code for all went well
66 * EX_ERROR Exit code for something failed
67 * EX_TBLERR Exit code for errors relating to device or lock tables
68 * EX_NOFREE Exit code for free failed
69 */
70
71 #define EX_OK 0
72 #define EX_ERROR 1
73 #define EX_TBLERR 2
74 #define EX_NOFREE 3
75
76
77 /*
78 * Messages
79 * M_USAGE Usage error
80 * M_INVKEY Invalid key specified
81 * M_NOTRSVD Attempting to free something not alloc'd
82 * M_NOTONKEY Attempting to free with wrong key
83 * M_DEVTAB Error opening the device table
84 * M_RSVTAB Error opening the device-reservation table
85 * M_ERROR Some internal error
86 */
87
88 #define M_USAGE "usage: devfree key [device [...]]"
89 #define M_INVKEY "Invalid key: %s"
90 #define M_NOTRSVD "Device not reserved: %s"
91 #define M_NOTONKEY "Cannot unreserve device: %s"
92 #define M_DEVTAB "Cannot open the device table: %s"
93 #define M_RSVTAB "Cannot open the device-reservation table: %s"
94 #define M_ERROR "Internal error, errno=%d"
95
96
97 /*
98 * Local functions and static data
99 * stdmsg(r,l,s,m) Macro for standard message generation
100 * r MM_NRECOV or MM_RECOV (recoverability)
101 * l Label
102 * s Severity
103 * m Message
104 * lbl Buffer for the label-component of a message.
105 * msg Buffer for the text-component of a message.
106 */
107
108 #define stdmsg(r,l,s,m) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,m,MM_NULLACT,MM_NULLTAG)
109
110 static char lbl[MM_MXLABELLN+1];
111 static char msg[MM_MXTXTLN+1];
112
113 /*
114 * devfree key [device [device [...]]]
115 *
116 * This command frees devices that have been reserved using
117 * the devreserv command (or the devreserv() function).
118 *
119 * Options: None
120 *
121 * Arguments:
122 * key The key on which the device to free was allocated on.
123 * If omitted, all keys are assumed.
124 * device The device to free. If omitted, all devices allocated
125 * using the key are freed.
126 *
127 * Command Values:
128 * EX_OK 0 Device(s) successfully freed
129 * EX_ERROR 1 A syntax error or other error occurred
130 * EX_TBLERR 2 A problem with device management tables
131 * EX_NOFREE 3 A requested device couldn't be freed
132 */
133
134 int
main(int argc,char * argv[])135 main(int argc, char *argv[])
136 {
137 /* Automatics */
138 char **argp; /* Ptr to current argument */
139 struct reservdev **rsvd; /* Ptr to list of locks */
140 struct reservdev **plk; /* Running ptr to locks */
141 char *devtab; /* Ptr to device table name */
142 char *rsvtab; /* Ptr to dev-rsv-tbl name */
143 char *p; /* Temp char pointer */
144 int argcount; /* Number of args on cmd */
145 long lkey; /* Key for locking (long) */
146 int key; /* Key for locking */
147 int halt; /* TRUE if we need to stop */
148 int sev; /* Message severity */
149 int exitcode; /* Value of command */
150 int syntaxerr; /* Flag, TRUE if syntax error */
151 int exitcd; /* Value for exit() */
152 int c; /* Option character */
153
154
155 /*
156 * Initializations
157 */
158
159 /* Build a message label */
160 if (p = strrchr(argv[0], '/')) p++;
161 else p = argv[0];
162 (void) strlcat(strcpy(lbl, "UX:"), p, sizeof(lbl));
163
164 /* Make only the text component of messages appear (remove this in SVR4.1) */
165 (void) putenv("MSGVERB=text");
166
167
168 /*
169 * Parse the options from the command line
170 */
171
172 opterr = 0;
173 syntaxerr = FALSE;
174 while ((c = getopt(argc, argv, "")) != EOF) switch(c) {
175 default:
176 syntaxerr = FALSE;
177 break;
178 }
179
180
181 /* Argument initializations */
182 argp = &argv[optind];
183 if ((argcount = argc-optind) < 1) syntaxerr = TRUE;
184
185
186 /* If there's (an obvious) syntax error, write a message and quit */
187 if (syntaxerr) {
188 stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE);
189 exit(EX_ERROR);
190 }
191
192
193 /*
194 * devfree key
195 *
196 * Free all devices that have been reserved using the key "key".
197 */
198
199 if (argcount == 1) {
200
201 /* Extract the key from the command */
202 lkey = strtol(*argp, &p, 10);
203 if (*p || (lkey <= 0) || (lkey > MAXINT)) {
204 (void) snprintf(msg, sizeof (msg), M_INVKEY, *argp);
205 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
206 exit(EX_ERROR);
207 }
208 key = (int) lkey;
209
210 /* Get the list of devices currently reserved */
211 if (rsvd = reservdev()) {
212 exitcd = EX_OK;
213 for (plk = rsvd ; *plk ; plk++) {
214 if ((*plk)->key == key)
215 if (devfree(key, (*plk)->devname) != 0)
216 exitcd = EX_NOFREE;
217 }
218 } else {
219 if (((errno == ENOENT) || (errno == EACCES)) && (rsvtab = _rsvtabpath())) {
220 (void) snprintf(msg, sizeof(msg), M_RSVTAB, rsvtab);
221 exitcd = EX_TBLERR;
222 sev = MM_ERROR;
223 } else {
224 (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
225 exitcd = EX_ERROR;
226 sev = MM_HALT;
227 }
228 stdmsg(MM_NRECOV, lbl, sev, msg);
229 }
230
231 /* Done */
232 exit(exitcd);
233 }
234
235
236 /*
237 * devfree key device [...]
238 *
239 * Free specific devices
240 */
241
242 /* Open the device file (if there's one to be opened) */
243 if (!_opendevtab("r")) {
244 if (devtab = _devtabpath()) {
245 (void) snprintf(msg, sizeof(msg), M_DEVTAB, devtab);
246 exitcd = EX_TBLERR;
247 sev = MM_ERROR;
248 } else {
249 (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
250 exitcd = EX_ERROR;
251 sev = MM_HALT;
252 }
253 stdmsg(MM_NRECOV, lbl, sev, msg);
254 exit(exitcd);
255 }
256
257 /* Extract the key from the command */
258 lkey = strtol(*argp, &p, 10);
259 if (*p || (lkey <= 0) || (lkey > MAXINT)) {
260 (void) snprintf(msg, sizeof(msg), M_INVKEY, *argp);
261 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
262 exit(EX_ERROR);
263 }
264 key = (int) lkey;
265 argp++;
266
267 /* Loop through the list of devices to free */
268 exitcode = EX_OK;
269 halt = FALSE;
270 while (!halt && *argp) {
271
272 /* Try to free the device */
273 if (devfree(key, *argp) != 0) {
274 if ((errno == EACCES) || (errno == ENOENT)) {
275
276 /* Can't get at reservation file */
277 if (rsvtab = _rsvtabpath()) {
278 exitcode = EX_TBLERR;
279 (void) snprintf(msg, sizeof(msg), M_RSVTAB, rsvtab);
280 sev = MM_ERROR;
281 }
282 else {
283 exitcode = EX_ERROR;
284 (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
285 sev = MM_HALT;
286 }
287 stdmsg(MM_NRECOV, lbl, sev, msg);
288 halt = TRUE;
289 }
290 else if (errno == EPERM) {
291
292 /* Wrong key */
293 (void) snprintf(msg, sizeof(msg), M_NOTONKEY, *argp);
294 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
295 exitcode = EX_NOFREE;
296 }
297 else if (errno == EINVAL) {
298
299 /* Device not reserved */
300 (void) snprintf(msg, sizeof(msg), M_NOTRSVD, *argp);
301 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
302 exitcode = EX_NOFREE;
303 }
304
305 else {
306
307 /* Some other strange error occurred */
308 (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
309 stdmsg(MM_NRECOV, lbl, MM_HALT, msg);
310 exitcode = EX_ERROR;
311 halt = TRUE;
312 }
313 }
314 argp++;
315 }
316
317
318 /* Exit with the appropriate code */
319 return(exitcode);
320 }
321