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