17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate * with the License.
87c478bd9Sstevel@tonic-gate *
97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate * and limitations under the License.
137c478bd9Sstevel@tonic-gate *
147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate *
207c478bd9Sstevel@tonic-gate * CDDL HEADER END
217c478bd9Sstevel@tonic-gate */
227c478bd9Sstevel@tonic-gate /*
23*113f4232Sakaplan * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
287c478bd9Sstevel@tonic-gate /* All Rights Reserved */
297c478bd9Sstevel@tonic-gate
307c478bd9Sstevel@tonic-gate
317c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
327c478bd9Sstevel@tonic-gate
337c478bd9Sstevel@tonic-gate /*
347c478bd9Sstevel@tonic-gate * devfree key [device [...]]
357c478bd9Sstevel@tonic-gate */
367c478bd9Sstevel@tonic-gate
377c478bd9Sstevel@tonic-gate #include <sys/types.h>
387c478bd9Sstevel@tonic-gate #include <sys/param.h>
397c478bd9Sstevel@tonic-gate #include <stdio.h>
407c478bd9Sstevel@tonic-gate #include <errno.h>
417c478bd9Sstevel@tonic-gate #include <stdlib.h>
427c478bd9Sstevel@tonic-gate #include <string.h>
437c478bd9Sstevel@tonic-gate #include <fmtmsg.h>
447c478bd9Sstevel@tonic-gate #include <devmgmt.h>
457c478bd9Sstevel@tonic-gate #include <values.h>
467c478bd9Sstevel@tonic-gate #include <devtab.h>
477c478bd9Sstevel@tonic-gate
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate * Local definitions
517c478bd9Sstevel@tonic-gate * TRUE Boolean TRUE value
527c478bd9Sstevel@tonic-gate * FALSE Boolean FALSE value
537c478bd9Sstevel@tonic-gate */
547c478bd9Sstevel@tonic-gate #ifndef TRUE
557c478bd9Sstevel@tonic-gate #define TRUE ('t')
567c478bd9Sstevel@tonic-gate #endif
577c478bd9Sstevel@tonic-gate
587c478bd9Sstevel@tonic-gate #ifndef FALSE
597c478bd9Sstevel@tonic-gate #define FALSE 0
607c478bd9Sstevel@tonic-gate #endif
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate * Exit codes:
657c478bd9Sstevel@tonic-gate * EX_OK Exit code for all went well
667c478bd9Sstevel@tonic-gate * EX_ERROR Exit code for something failed
677c478bd9Sstevel@tonic-gate * EX_TBLERR Exit code for errors relating to device or lock tables
687c478bd9Sstevel@tonic-gate * EX_NOFREE Exit code for free failed
697c478bd9Sstevel@tonic-gate */
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate #define EX_OK 0
727c478bd9Sstevel@tonic-gate #define EX_ERROR 1
737c478bd9Sstevel@tonic-gate #define EX_TBLERR 2
747c478bd9Sstevel@tonic-gate #define EX_NOFREE 3
757c478bd9Sstevel@tonic-gate
767c478bd9Sstevel@tonic-gate
777c478bd9Sstevel@tonic-gate /*
787c478bd9Sstevel@tonic-gate * Messages
797c478bd9Sstevel@tonic-gate * M_USAGE Usage error
807c478bd9Sstevel@tonic-gate * M_INVKEY Invalid key specified
817c478bd9Sstevel@tonic-gate * M_NOTRSVD Attempting to free something not alloc'd
827c478bd9Sstevel@tonic-gate * M_NOTONKEY Attempting to free with wrong key
837c478bd9Sstevel@tonic-gate * M_DEVTAB Error opening the device table
847c478bd9Sstevel@tonic-gate * M_RSVTAB Error opening the device-reservation table
857c478bd9Sstevel@tonic-gate * M_ERROR Some internal error
867c478bd9Sstevel@tonic-gate */
877c478bd9Sstevel@tonic-gate
887c478bd9Sstevel@tonic-gate #define M_USAGE "usage: devfree key [device [...]]"
897c478bd9Sstevel@tonic-gate #define M_INVKEY "Invalid key: %s"
907c478bd9Sstevel@tonic-gate #define M_NOTRSVD "Device not reserved: %s"
917c478bd9Sstevel@tonic-gate #define M_NOTONKEY "Cannot unreserve device: %s"
927c478bd9Sstevel@tonic-gate #define M_DEVTAB "Cannot open the device table: %s"
937c478bd9Sstevel@tonic-gate #define M_RSVTAB "Cannot open the device-reservation table: %s"
947c478bd9Sstevel@tonic-gate #define M_ERROR "Internal error, errno=%d"
957c478bd9Sstevel@tonic-gate
967c478bd9Sstevel@tonic-gate
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate * Local functions and static data
997c478bd9Sstevel@tonic-gate * stdmsg(r,l,s,m) Macro for standard message generation
1007c478bd9Sstevel@tonic-gate * r MM_NRECOV or MM_RECOV (recoverability)
1017c478bd9Sstevel@tonic-gate * l Label
1027c478bd9Sstevel@tonic-gate * s Severity
1037c478bd9Sstevel@tonic-gate * m Message
1047c478bd9Sstevel@tonic-gate * lbl Buffer for the label-component of a message.
1057c478bd9Sstevel@tonic-gate * msg Buffer for the text-component of a message.
1067c478bd9Sstevel@tonic-gate */
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate #define stdmsg(r,l,s,m) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,m,MM_NULLACT,MM_NULLTAG)
1097c478bd9Sstevel@tonic-gate
1107c478bd9Sstevel@tonic-gate static char lbl[MM_MXLABELLN+1];
1117c478bd9Sstevel@tonic-gate static char msg[MM_MXTXTLN+1];
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate /*
1147c478bd9Sstevel@tonic-gate * devfree key [device [device [...]]]
1157c478bd9Sstevel@tonic-gate *
1167c478bd9Sstevel@tonic-gate * This command frees devices that have been reserved using
1177c478bd9Sstevel@tonic-gate * the devreserv command (or the devreserv() function).
1187c478bd9Sstevel@tonic-gate *
1197c478bd9Sstevel@tonic-gate * Options: None
1207c478bd9Sstevel@tonic-gate *
1217c478bd9Sstevel@tonic-gate * Arguments:
1227c478bd9Sstevel@tonic-gate * key The key on which the device to free was allocated on.
1237c478bd9Sstevel@tonic-gate * If omitted, all keys are assumed.
1247c478bd9Sstevel@tonic-gate * device The device to free. If omitted, all devices allocated
1257c478bd9Sstevel@tonic-gate * using the key are freed.
1267c478bd9Sstevel@tonic-gate *
1277c478bd9Sstevel@tonic-gate * Command Values:
1287c478bd9Sstevel@tonic-gate * EX_OK 0 Device(s) successfully freed
1297c478bd9Sstevel@tonic-gate * EX_ERROR 1 A syntax error or other error occurred
1307c478bd9Sstevel@tonic-gate * EX_TBLERR 2 A problem with device management tables
1317c478bd9Sstevel@tonic-gate * EX_NOFREE 3 A requested device couldn't be freed
1327c478bd9Sstevel@tonic-gate */
1337c478bd9Sstevel@tonic-gate
134*113f4232Sakaplan int
main(int argc,char * argv[])135*113f4232Sakaplan main(int argc, char *argv[])
1367c478bd9Sstevel@tonic-gate {
1377c478bd9Sstevel@tonic-gate /* Automatics */
1387c478bd9Sstevel@tonic-gate char **argp; /* Ptr to current argument */
1397c478bd9Sstevel@tonic-gate struct reservdev **rsvd; /* Ptr to list of locks */
1407c478bd9Sstevel@tonic-gate struct reservdev **plk; /* Running ptr to locks */
1417c478bd9Sstevel@tonic-gate char *devtab; /* Ptr to device table name */
1427c478bd9Sstevel@tonic-gate char *rsvtab; /* Ptr to dev-rsv-tbl name */
1437c478bd9Sstevel@tonic-gate char *p; /* Temp char pointer */
1447c478bd9Sstevel@tonic-gate int argcount; /* Number of args on cmd */
1457c478bd9Sstevel@tonic-gate long lkey; /* Key for locking (long) */
1467c478bd9Sstevel@tonic-gate int key; /* Key for locking */
1477c478bd9Sstevel@tonic-gate int halt; /* TRUE if we need to stop */
1487c478bd9Sstevel@tonic-gate int sev; /* Message severity */
1497c478bd9Sstevel@tonic-gate int exitcode; /* Value of command */
1507c478bd9Sstevel@tonic-gate int syntaxerr; /* Flag, TRUE if syntax error */
1517c478bd9Sstevel@tonic-gate int exitcd; /* Value for exit() */
1527c478bd9Sstevel@tonic-gate int c; /* Option character */
1537c478bd9Sstevel@tonic-gate
1547c478bd9Sstevel@tonic-gate
1557c478bd9Sstevel@tonic-gate /*
1567c478bd9Sstevel@tonic-gate * Initializations
1577c478bd9Sstevel@tonic-gate */
1587c478bd9Sstevel@tonic-gate
1597c478bd9Sstevel@tonic-gate /* Build a message label */
1607c478bd9Sstevel@tonic-gate if (p = strrchr(argv[0], '/')) p++;
1617c478bd9Sstevel@tonic-gate else p = argv[0];
1627c478bd9Sstevel@tonic-gate (void) strlcat(strcpy(lbl, "UX:"), p, sizeof(lbl));
1637c478bd9Sstevel@tonic-gate
1647c478bd9Sstevel@tonic-gate /* Make only the text component of messages appear (remove this in SVR4.1) */
1657c478bd9Sstevel@tonic-gate (void) putenv("MSGVERB=text");
1667c478bd9Sstevel@tonic-gate
1677c478bd9Sstevel@tonic-gate
1687c478bd9Sstevel@tonic-gate /*
1697c478bd9Sstevel@tonic-gate * Parse the options from the command line
1707c478bd9Sstevel@tonic-gate */
1717c478bd9Sstevel@tonic-gate
1727c478bd9Sstevel@tonic-gate opterr = 0;
1737c478bd9Sstevel@tonic-gate syntaxerr = FALSE;
1747c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "")) != EOF) switch(c) {
1757c478bd9Sstevel@tonic-gate default:
1767c478bd9Sstevel@tonic-gate syntaxerr = FALSE;
1777c478bd9Sstevel@tonic-gate break;
1787c478bd9Sstevel@tonic-gate }
1797c478bd9Sstevel@tonic-gate
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate /* Argument initializations */
1827c478bd9Sstevel@tonic-gate argp = &argv[optind];
1837c478bd9Sstevel@tonic-gate if ((argcount = argc-optind) < 1) syntaxerr = TRUE;
1847c478bd9Sstevel@tonic-gate
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate /* If there's (an obvious) syntax error, write a message and quit */
1877c478bd9Sstevel@tonic-gate if (syntaxerr) {
1887c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE);
1897c478bd9Sstevel@tonic-gate exit(EX_ERROR);
1907c478bd9Sstevel@tonic-gate }
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate
1937c478bd9Sstevel@tonic-gate /*
1947c478bd9Sstevel@tonic-gate * devfree key
1957c478bd9Sstevel@tonic-gate *
1967c478bd9Sstevel@tonic-gate * Free all devices that have been reserved using the key "key".
1977c478bd9Sstevel@tonic-gate */
1987c478bd9Sstevel@tonic-gate
1997c478bd9Sstevel@tonic-gate if (argcount == 1) {
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate /* Extract the key from the command */
2027c478bd9Sstevel@tonic-gate lkey = strtol(*argp, &p, 10);
2037c478bd9Sstevel@tonic-gate if (*p || (lkey <= 0) || (lkey > MAXINT)) {
2047c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), M_INVKEY, *argp);
2057c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
2067c478bd9Sstevel@tonic-gate exit(EX_ERROR);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate key = (int) lkey;
2097c478bd9Sstevel@tonic-gate
2107c478bd9Sstevel@tonic-gate /* Get the list of devices currently reserved */
2117c478bd9Sstevel@tonic-gate if (rsvd = reservdev()) {
2127c478bd9Sstevel@tonic-gate exitcd = EX_OK;
2137c478bd9Sstevel@tonic-gate for (plk = rsvd ; *plk ; plk++) {
2147c478bd9Sstevel@tonic-gate if ((*plk)->key == key)
2157c478bd9Sstevel@tonic-gate if (devfree(key, (*plk)->devname) != 0)
2167c478bd9Sstevel@tonic-gate exitcd = EX_NOFREE;
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate } else {
2197c478bd9Sstevel@tonic-gate if (((errno == ENOENT) || (errno == EACCES)) && (rsvtab = _rsvtabpath())) {
2207c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_RSVTAB, rsvtab);
2217c478bd9Sstevel@tonic-gate exitcd = EX_TBLERR;
2227c478bd9Sstevel@tonic-gate sev = MM_ERROR;
2237c478bd9Sstevel@tonic-gate } else {
2247c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
2257c478bd9Sstevel@tonic-gate exitcd = EX_ERROR;
2267c478bd9Sstevel@tonic-gate sev = MM_HALT;
2277c478bd9Sstevel@tonic-gate }
2287c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, sev, msg);
2297c478bd9Sstevel@tonic-gate }
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate /* Done */
2327c478bd9Sstevel@tonic-gate exit(exitcd);
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate
2357c478bd9Sstevel@tonic-gate
2367c478bd9Sstevel@tonic-gate /*
2377c478bd9Sstevel@tonic-gate * devfree key device [...]
2387c478bd9Sstevel@tonic-gate *
2397c478bd9Sstevel@tonic-gate * Free specific devices
2407c478bd9Sstevel@tonic-gate */
2417c478bd9Sstevel@tonic-gate
2427c478bd9Sstevel@tonic-gate /* Open the device file (if there's one to be opened) */
2437c478bd9Sstevel@tonic-gate if (!_opendevtab("r")) {
2447c478bd9Sstevel@tonic-gate if (devtab = _devtabpath()) {
2457c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_DEVTAB, devtab);
2467c478bd9Sstevel@tonic-gate exitcd = EX_TBLERR;
2477c478bd9Sstevel@tonic-gate sev = MM_ERROR;
2487c478bd9Sstevel@tonic-gate } else {
2497c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
2507c478bd9Sstevel@tonic-gate exitcd = EX_ERROR;
2517c478bd9Sstevel@tonic-gate sev = MM_HALT;
2527c478bd9Sstevel@tonic-gate }
2537c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, sev, msg);
2547c478bd9Sstevel@tonic-gate exit(exitcd);
2557c478bd9Sstevel@tonic-gate }
2567c478bd9Sstevel@tonic-gate
2577c478bd9Sstevel@tonic-gate /* Extract the key from the command */
2587c478bd9Sstevel@tonic-gate lkey = strtol(*argp, &p, 10);
2597c478bd9Sstevel@tonic-gate if (*p || (lkey <= 0) || (lkey > MAXINT)) {
2607c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_INVKEY, *argp);
2617c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
2627c478bd9Sstevel@tonic-gate exit(EX_ERROR);
2637c478bd9Sstevel@tonic-gate }
2647c478bd9Sstevel@tonic-gate key = (int) lkey;
2657c478bd9Sstevel@tonic-gate argp++;
2667c478bd9Sstevel@tonic-gate
2677c478bd9Sstevel@tonic-gate /* Loop through the list of devices to free */
2687c478bd9Sstevel@tonic-gate exitcode = EX_OK;
2697c478bd9Sstevel@tonic-gate halt = FALSE;
2707c478bd9Sstevel@tonic-gate while (!halt && *argp) {
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate /* Try to free the device */
2737c478bd9Sstevel@tonic-gate if (devfree(key, *argp) != 0) {
2747c478bd9Sstevel@tonic-gate if ((errno == EACCES) || (errno == ENOENT)) {
2757c478bd9Sstevel@tonic-gate
2767c478bd9Sstevel@tonic-gate /* Can't get at reservation file */
2777c478bd9Sstevel@tonic-gate if (rsvtab = _rsvtabpath()) {
2787c478bd9Sstevel@tonic-gate exitcode = EX_TBLERR;
2797c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_RSVTAB, rsvtab);
2807c478bd9Sstevel@tonic-gate sev = MM_ERROR;
2817c478bd9Sstevel@tonic-gate }
2827c478bd9Sstevel@tonic-gate else {
2837c478bd9Sstevel@tonic-gate exitcode = EX_ERROR;
2847c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
2857c478bd9Sstevel@tonic-gate sev = MM_HALT;
2867c478bd9Sstevel@tonic-gate }
2877c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, sev, msg);
2887c478bd9Sstevel@tonic-gate halt = TRUE;
2897c478bd9Sstevel@tonic-gate }
2907c478bd9Sstevel@tonic-gate else if (errno == EPERM) {
2917c478bd9Sstevel@tonic-gate
2927c478bd9Sstevel@tonic-gate /* Wrong key */
2937c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_NOTONKEY, *argp);
2947c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
2957c478bd9Sstevel@tonic-gate exitcode = EX_NOFREE;
2967c478bd9Sstevel@tonic-gate }
2977c478bd9Sstevel@tonic-gate else if (errno == EINVAL) {
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate /* Device not reserved */
3007c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_NOTRSVD, *argp);
3017c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
3027c478bd9Sstevel@tonic-gate exitcode = EX_NOFREE;
3037c478bd9Sstevel@tonic-gate }
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate else {
3067c478bd9Sstevel@tonic-gate
3077c478bd9Sstevel@tonic-gate /* Some other strange error occurred */
3087c478bd9Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
3097c478bd9Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_HALT, msg);
3107c478bd9Sstevel@tonic-gate exitcode = EX_ERROR;
3117c478bd9Sstevel@tonic-gate halt = TRUE;
3127c478bd9Sstevel@tonic-gate }
3137c478bd9Sstevel@tonic-gate }
3147c478bd9Sstevel@tonic-gate argp++;
3157c478bd9Sstevel@tonic-gate }
3167c478bd9Sstevel@tonic-gate
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate /* Exit with the appropriate code */
3197c478bd9Sstevel@tonic-gate return(exitcode);
3207c478bd9Sstevel@tonic-gate }
321