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 * Local definitions
47 * TRUE Boolean TRUE value
48 * FALSE Boolean FALSE value
49 */
50 #ifndef TRUE
51 #define TRUE ('t')
52 #endif
53
54 #ifndef FALSE
55 #define FALSE 0
56 #endif
57
58
59 /*
60 * Exit codes:
61 * EX_OK Exit code for all went well
62 * EX_ERROR Exit code for something failed
63 * EX_TBLERR Exit code for errors relating to device or lock tables
64 * EX_NOFREE Exit code for free failed
65 */
66
67 #define EX_OK 0
68 #define EX_ERROR 1
69 #define EX_TBLERR 2
70 #define EX_NOFREE 3
71
72
73 /*
74 * Messages
75 * M_USAGE Usage error
76 * M_INVKEY Invalid key specified
77 * M_NOTRSVD Attempting to free something not alloc'd
78 * M_NOTONKEY Attempting to free with wrong key
79 * M_DEVTAB Error opening the device table
80 * M_RSVTAB Error opening the device-reservation table
81 * M_ERROR Some internal error
82 */
83
84 #define M_USAGE "usage: devfree key [device [...]]"
85 #define M_INVKEY "Invalid key: %s"
86 #define M_NOTRSVD "Device not reserved: %s"
87 #define M_NOTONKEY "Cannot unreserve device: %s"
88 #define M_DEVTAB "Cannot open the device table: %s"
89 #define M_RSVTAB "Cannot open the device-reservation table: %s"
90 #define M_ERROR "Internal error, errno=%d"
91
92
93 /*
94 * Local functions and static data
95 * stdmsg(r,l,s,m) Macro for standard message generation
96 * r MM_NRECOV or MM_RECOV (recoverability)
97 * l Label
98 * s Severity
99 * m Message
100 * lbl Buffer for the label-component of a message.
101 * msg Buffer for the text-component of a message.
102 */
103
104 #define stdmsg(r, l, s, m) \
105 (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 const char *errstr;
151
152
153 /*
154 * Initializations
155 */
156
157 /* Build a message label */
158 if (p = strrchr(argv[0], '/'))
159 p++;
160 else
161 p = argv[0];
162 (void) strlcat(strcpy(lbl, "UX:"), p, sizeof (lbl));
163
164 /*
165 * Make only the text component of messages appear
166 * (remove this in SVR4.1)
167 */
168 (void) putenv("MSGVERB=text");
169
170
171 /*
172 * Parse the options from the command line
173 */
174
175 opterr = 0;
176 syntaxerr = FALSE;
177 while ((c = getopt(argc, argv, "")) != EOF) {
178 switch (c) {
179 default:
180 syntaxerr = FALSE;
181 break;
182 }
183 }
184
185
186 /* Argument initializations */
187 argp = &argv[optind];
188 if ((argcount = argc-optind) < 1)
189 syntaxerr = TRUE;
190
191
192 /* If there's (an obvious) syntax error, write a message and quit */
193 if (syntaxerr) {
194 stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE);
195 exit(EX_ERROR);
196 }
197
198
199 /*
200 * devfree key
201 *
202 * Free all devices that have been reserved using the key "key".
203 */
204
205 if (argcount == 1) {
206
207 /* Extract the key from the command */
208 lkey = strtonum(*argp, 1, MAXINT, &errstr);
209 if (errstr != NULL) {
210 (void) snprintf(msg, sizeof (msg), M_INVKEY, *argp);
211 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
212 exit(EX_ERROR);
213 }
214 key = (int)lkey;
215
216 /* Get the list of devices currently reserved */
217 if (rsvd = reservdev()) {
218 exitcd = EX_OK;
219 for (plk = rsvd; *plk; plk++) {
220 if ((*plk)->key == key)
221 if (devfree(key, (*plk)->devname) != 0)
222 exitcd = EX_NOFREE;
223 }
224 } else {
225 if (((errno == ENOENT) || (errno == EACCES)) &&
226 (rsvtab = _rsvtabpath())) {
227 (void) snprintf(msg, sizeof (msg), M_RSVTAB,
228 rsvtab);
229 exitcd = EX_TBLERR;
230 sev = MM_ERROR;
231 } else {
232 (void) snprintf(msg, sizeof (msg), M_ERROR,
233 errno);
234 exitcd = EX_ERROR;
235 sev = MM_HALT;
236 }
237 stdmsg(MM_NRECOV, lbl, sev, msg);
238 }
239
240 /* Done */
241 exit(exitcd);
242 }
243
244
245 /*
246 * devfree key device [...]
247 *
248 * Free specific devices
249 */
250
251 /* Open the device file (if there's one to be opened) */
252 if (!_opendevtab("r")) {
253 if (devtab = _devtabpath()) {
254 (void) snprintf(msg, sizeof (msg), M_DEVTAB, devtab);
255 exitcd = EX_TBLERR;
256 sev = MM_ERROR;
257 } else {
258 (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
259 exitcd = EX_ERROR;
260 sev = MM_HALT;
261 }
262 stdmsg(MM_NRECOV, lbl, sev, msg);
263 exit(exitcd);
264 }
265
266 /* Extract the key from the command */
267 lkey = strtonum(*argp, 1, MAXINT, &errstr);
268 if (errstr != NULL) {
269 (void) snprintf(msg, sizeof (msg), M_INVKEY, *argp);
270 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
271 exit(EX_ERROR);
272 }
273 key = (int)lkey;
274 argp++;
275
276 /* Loop through the list of devices to free */
277 exitcode = EX_OK;
278 halt = FALSE;
279 while (!halt && *argp) {
280
281 /* Try to free the device */
282 if (devfree(key, *argp) != 0) {
283 if ((errno == EACCES) || (errno == ENOENT)) {
284
285 /* Can't get at reservation file */
286 if (rsvtab = _rsvtabpath()) {
287 exitcode = EX_TBLERR;
288 (void) snprintf(msg, sizeof (msg),
289 M_RSVTAB, rsvtab);
290 sev = MM_ERROR;
291 } else {
292 exitcode = EX_ERROR;
293 (void) snprintf(msg, sizeof (msg),
294 M_ERROR, errno);
295 sev = MM_HALT;
296 }
297 stdmsg(MM_NRECOV, lbl, sev, msg);
298 halt = TRUE;
299 } else if (errno == EPERM) {
300
301 /* Wrong key */
302 (void) snprintf(msg, sizeof (msg), M_NOTONKEY,
303 *argp);
304 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
305 exitcode = EX_NOFREE;
306 } else if (errno == EINVAL) {
307
308 /* Device not reserved */
309 (void) snprintf(msg, sizeof (msg), M_NOTRSVD,
310 *argp);
311 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
312 exitcode = EX_NOFREE;
313 } else {
314
315 /* Some other strange error occurred */
316 (void) snprintf(msg, sizeof (msg), M_ERROR,
317 errno);
318 stdmsg(MM_NRECOV, lbl, MM_HALT, msg);
319 exitcode = EX_ERROR;
320 halt = TRUE;
321 }
322 }
323 argp++;
324 }
325
326 /* Exit with the appropriate code */
327 return (exitcode);
328 }
329