10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance
70Sstevel@tonic-gate * with the License.
80Sstevel@tonic-gate *
90Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate * See the License for the specific language governing permissions
120Sstevel@tonic-gate * and limitations under the License.
130Sstevel@tonic-gate *
140Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate *
200Sstevel@tonic-gate * CDDL HEADER END
210Sstevel@tonic-gate */
220Sstevel@tonic-gate /*
23*644Sakaplan * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
240Sstevel@tonic-gate * Use is subject to license terms.
250Sstevel@tonic-gate */
260Sstevel@tonic-gate
270Sstevel@tonic-gate /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
280Sstevel@tonic-gate /* All Rights Reserved */
290Sstevel@tonic-gate
300Sstevel@tonic-gate
310Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI"
320Sstevel@tonic-gate
330Sstevel@tonic-gate /*
340Sstevel@tonic-gate * devfree key [device [...]]
350Sstevel@tonic-gate */
360Sstevel@tonic-gate
370Sstevel@tonic-gate #include <sys/types.h>
380Sstevel@tonic-gate #include <sys/param.h>
390Sstevel@tonic-gate #include <stdio.h>
400Sstevel@tonic-gate #include <errno.h>
410Sstevel@tonic-gate #include <stdlib.h>
420Sstevel@tonic-gate #include <string.h>
430Sstevel@tonic-gate #include <fmtmsg.h>
440Sstevel@tonic-gate #include <devmgmt.h>
450Sstevel@tonic-gate #include <values.h>
460Sstevel@tonic-gate #include <devtab.h>
470Sstevel@tonic-gate
480Sstevel@tonic-gate
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate * Local definitions
510Sstevel@tonic-gate * TRUE Boolean TRUE value
520Sstevel@tonic-gate * FALSE Boolean FALSE value
530Sstevel@tonic-gate */
540Sstevel@tonic-gate #ifndef TRUE
550Sstevel@tonic-gate #define TRUE ('t')
560Sstevel@tonic-gate #endif
570Sstevel@tonic-gate
580Sstevel@tonic-gate #ifndef FALSE
590Sstevel@tonic-gate #define FALSE 0
600Sstevel@tonic-gate #endif
610Sstevel@tonic-gate
620Sstevel@tonic-gate
630Sstevel@tonic-gate /*
640Sstevel@tonic-gate * Exit codes:
650Sstevel@tonic-gate * EX_OK Exit code for all went well
660Sstevel@tonic-gate * EX_ERROR Exit code for something failed
670Sstevel@tonic-gate * EX_TBLERR Exit code for errors relating to device or lock tables
680Sstevel@tonic-gate * EX_NOFREE Exit code for free failed
690Sstevel@tonic-gate */
700Sstevel@tonic-gate
710Sstevel@tonic-gate #define EX_OK 0
720Sstevel@tonic-gate #define EX_ERROR 1
730Sstevel@tonic-gate #define EX_TBLERR 2
740Sstevel@tonic-gate #define EX_NOFREE 3
750Sstevel@tonic-gate
760Sstevel@tonic-gate
770Sstevel@tonic-gate /*
780Sstevel@tonic-gate * Messages
790Sstevel@tonic-gate * M_USAGE Usage error
800Sstevel@tonic-gate * M_INVKEY Invalid key specified
810Sstevel@tonic-gate * M_NOTRSVD Attempting to free something not alloc'd
820Sstevel@tonic-gate * M_NOTONKEY Attempting to free with wrong key
830Sstevel@tonic-gate * M_DEVTAB Error opening the device table
840Sstevel@tonic-gate * M_RSVTAB Error opening the device-reservation table
850Sstevel@tonic-gate * M_ERROR Some internal error
860Sstevel@tonic-gate */
870Sstevel@tonic-gate
880Sstevel@tonic-gate #define M_USAGE "usage: devfree key [device [...]]"
890Sstevel@tonic-gate #define M_INVKEY "Invalid key: %s"
900Sstevel@tonic-gate #define M_NOTRSVD "Device not reserved: %s"
910Sstevel@tonic-gate #define M_NOTONKEY "Cannot unreserve device: %s"
920Sstevel@tonic-gate #define M_DEVTAB "Cannot open the device table: %s"
930Sstevel@tonic-gate #define M_RSVTAB "Cannot open the device-reservation table: %s"
940Sstevel@tonic-gate #define M_ERROR "Internal error, errno=%d"
950Sstevel@tonic-gate
960Sstevel@tonic-gate
970Sstevel@tonic-gate /*
980Sstevel@tonic-gate * Local functions and static data
990Sstevel@tonic-gate * stdmsg(r,l,s,m) Macro for standard message generation
1000Sstevel@tonic-gate * r MM_NRECOV or MM_RECOV (recoverability)
1010Sstevel@tonic-gate * l Label
1020Sstevel@tonic-gate * s Severity
1030Sstevel@tonic-gate * m Message
1040Sstevel@tonic-gate * lbl Buffer for the label-component of a message.
1050Sstevel@tonic-gate * msg Buffer for the text-component of a message.
1060Sstevel@tonic-gate */
1070Sstevel@tonic-gate
1080Sstevel@tonic-gate #define stdmsg(r,l,s,m) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,m,MM_NULLACT,MM_NULLTAG)
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate static char lbl[MM_MXLABELLN+1];
1110Sstevel@tonic-gate static char msg[MM_MXTXTLN+1];
1120Sstevel@tonic-gate
1130Sstevel@tonic-gate /*
1140Sstevel@tonic-gate * devfree key [device [device [...]]]
1150Sstevel@tonic-gate *
1160Sstevel@tonic-gate * This command frees devices that have been reserved using
1170Sstevel@tonic-gate * the devreserv command (or the devreserv() function).
1180Sstevel@tonic-gate *
1190Sstevel@tonic-gate * Options: None
1200Sstevel@tonic-gate *
1210Sstevel@tonic-gate * Arguments:
1220Sstevel@tonic-gate * key The key on which the device to free was allocated on.
1230Sstevel@tonic-gate * If omitted, all keys are assumed.
1240Sstevel@tonic-gate * device The device to free. If omitted, all devices allocated
1250Sstevel@tonic-gate * using the key are freed.
1260Sstevel@tonic-gate *
1270Sstevel@tonic-gate * Command Values:
1280Sstevel@tonic-gate * EX_OK 0 Device(s) successfully freed
1290Sstevel@tonic-gate * EX_ERROR 1 A syntax error or other error occurred
1300Sstevel@tonic-gate * EX_TBLERR 2 A problem with device management tables
1310Sstevel@tonic-gate * EX_NOFREE 3 A requested device couldn't be freed
1320Sstevel@tonic-gate */
1330Sstevel@tonic-gate
134*644Sakaplan int
main(int argc,char * argv[])135*644Sakaplan main(int argc, char *argv[])
1360Sstevel@tonic-gate {
1370Sstevel@tonic-gate /* Automatics */
1380Sstevel@tonic-gate char **argp; /* Ptr to current argument */
1390Sstevel@tonic-gate struct reservdev **rsvd; /* Ptr to list of locks */
1400Sstevel@tonic-gate struct reservdev **plk; /* Running ptr to locks */
1410Sstevel@tonic-gate char *devtab; /* Ptr to device table name */
1420Sstevel@tonic-gate char *rsvtab; /* Ptr to dev-rsv-tbl name */
1430Sstevel@tonic-gate char *p; /* Temp char pointer */
1440Sstevel@tonic-gate int argcount; /* Number of args on cmd */
1450Sstevel@tonic-gate long lkey; /* Key for locking (long) */
1460Sstevel@tonic-gate int key; /* Key for locking */
1470Sstevel@tonic-gate int halt; /* TRUE if we need to stop */
1480Sstevel@tonic-gate int sev; /* Message severity */
1490Sstevel@tonic-gate int exitcode; /* Value of command */
1500Sstevel@tonic-gate int syntaxerr; /* Flag, TRUE if syntax error */
1510Sstevel@tonic-gate int exitcd; /* Value for exit() */
1520Sstevel@tonic-gate int c; /* Option character */
1530Sstevel@tonic-gate
1540Sstevel@tonic-gate
1550Sstevel@tonic-gate /*
1560Sstevel@tonic-gate * Initializations
1570Sstevel@tonic-gate */
1580Sstevel@tonic-gate
1590Sstevel@tonic-gate /* Build a message label */
1600Sstevel@tonic-gate if (p = strrchr(argv[0], '/')) p++;
1610Sstevel@tonic-gate else p = argv[0];
1620Sstevel@tonic-gate (void) strlcat(strcpy(lbl, "UX:"), p, sizeof(lbl));
1630Sstevel@tonic-gate
1640Sstevel@tonic-gate /* Make only the text component of messages appear (remove this in SVR4.1) */
1650Sstevel@tonic-gate (void) putenv("MSGVERB=text");
1660Sstevel@tonic-gate
1670Sstevel@tonic-gate
1680Sstevel@tonic-gate /*
1690Sstevel@tonic-gate * Parse the options from the command line
1700Sstevel@tonic-gate */
1710Sstevel@tonic-gate
1720Sstevel@tonic-gate opterr = 0;
1730Sstevel@tonic-gate syntaxerr = FALSE;
1740Sstevel@tonic-gate while ((c = getopt(argc, argv, "")) != EOF) switch(c) {
1750Sstevel@tonic-gate default:
1760Sstevel@tonic-gate syntaxerr = FALSE;
1770Sstevel@tonic-gate break;
1780Sstevel@tonic-gate }
1790Sstevel@tonic-gate
1800Sstevel@tonic-gate
1810Sstevel@tonic-gate /* Argument initializations */
1820Sstevel@tonic-gate argp = &argv[optind];
1830Sstevel@tonic-gate if ((argcount = argc-optind) < 1) syntaxerr = TRUE;
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate
1860Sstevel@tonic-gate /* If there's (an obvious) syntax error, write a message and quit */
1870Sstevel@tonic-gate if (syntaxerr) {
1880Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE);
1890Sstevel@tonic-gate exit(EX_ERROR);
1900Sstevel@tonic-gate }
1910Sstevel@tonic-gate
1920Sstevel@tonic-gate
1930Sstevel@tonic-gate /*
1940Sstevel@tonic-gate * devfree key
1950Sstevel@tonic-gate *
1960Sstevel@tonic-gate * Free all devices that have been reserved using the key "key".
1970Sstevel@tonic-gate */
1980Sstevel@tonic-gate
1990Sstevel@tonic-gate if (argcount == 1) {
2000Sstevel@tonic-gate
2010Sstevel@tonic-gate /* Extract the key from the command */
2020Sstevel@tonic-gate lkey = strtol(*argp, &p, 10);
2030Sstevel@tonic-gate if (*p || (lkey <= 0) || (lkey > MAXINT)) {
2040Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), M_INVKEY, *argp);
2050Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
2060Sstevel@tonic-gate exit(EX_ERROR);
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate key = (int) lkey;
2090Sstevel@tonic-gate
2100Sstevel@tonic-gate /* Get the list of devices currently reserved */
2110Sstevel@tonic-gate if (rsvd = reservdev()) {
2120Sstevel@tonic-gate exitcd = EX_OK;
2130Sstevel@tonic-gate for (plk = rsvd ; *plk ; plk++) {
2140Sstevel@tonic-gate if ((*plk)->key == key)
2150Sstevel@tonic-gate if (devfree(key, (*plk)->devname) != 0)
2160Sstevel@tonic-gate exitcd = EX_NOFREE;
2170Sstevel@tonic-gate }
2180Sstevel@tonic-gate } else {
2190Sstevel@tonic-gate if (((errno == ENOENT) || (errno == EACCES)) && (rsvtab = _rsvtabpath())) {
2200Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_RSVTAB, rsvtab);
2210Sstevel@tonic-gate exitcd = EX_TBLERR;
2220Sstevel@tonic-gate sev = MM_ERROR;
2230Sstevel@tonic-gate } else {
2240Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
2250Sstevel@tonic-gate exitcd = EX_ERROR;
2260Sstevel@tonic-gate sev = MM_HALT;
2270Sstevel@tonic-gate }
2280Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, sev, msg);
2290Sstevel@tonic-gate }
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate /* Done */
2320Sstevel@tonic-gate exit(exitcd);
2330Sstevel@tonic-gate }
2340Sstevel@tonic-gate
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate /*
2370Sstevel@tonic-gate * devfree key device [...]
2380Sstevel@tonic-gate *
2390Sstevel@tonic-gate * Free specific devices
2400Sstevel@tonic-gate */
2410Sstevel@tonic-gate
2420Sstevel@tonic-gate /* Open the device file (if there's one to be opened) */
2430Sstevel@tonic-gate if (!_opendevtab("r")) {
2440Sstevel@tonic-gate if (devtab = _devtabpath()) {
2450Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_DEVTAB, devtab);
2460Sstevel@tonic-gate exitcd = EX_TBLERR;
2470Sstevel@tonic-gate sev = MM_ERROR;
2480Sstevel@tonic-gate } else {
2490Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
2500Sstevel@tonic-gate exitcd = EX_ERROR;
2510Sstevel@tonic-gate sev = MM_HALT;
2520Sstevel@tonic-gate }
2530Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, sev, msg);
2540Sstevel@tonic-gate exit(exitcd);
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate /* Extract the key from the command */
2580Sstevel@tonic-gate lkey = strtol(*argp, &p, 10);
2590Sstevel@tonic-gate if (*p || (lkey <= 0) || (lkey > MAXINT)) {
2600Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_INVKEY, *argp);
2610Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
2620Sstevel@tonic-gate exit(EX_ERROR);
2630Sstevel@tonic-gate }
2640Sstevel@tonic-gate key = (int) lkey;
2650Sstevel@tonic-gate argp++;
2660Sstevel@tonic-gate
2670Sstevel@tonic-gate /* Loop through the list of devices to free */
2680Sstevel@tonic-gate exitcode = EX_OK;
2690Sstevel@tonic-gate halt = FALSE;
2700Sstevel@tonic-gate while (!halt && *argp) {
2710Sstevel@tonic-gate
2720Sstevel@tonic-gate /* Try to free the device */
2730Sstevel@tonic-gate if (devfree(key, *argp) != 0) {
2740Sstevel@tonic-gate if ((errno == EACCES) || (errno == ENOENT)) {
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate /* Can't get at reservation file */
2770Sstevel@tonic-gate if (rsvtab = _rsvtabpath()) {
2780Sstevel@tonic-gate exitcode = EX_TBLERR;
2790Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_RSVTAB, rsvtab);
2800Sstevel@tonic-gate sev = MM_ERROR;
2810Sstevel@tonic-gate }
2820Sstevel@tonic-gate else {
2830Sstevel@tonic-gate exitcode = EX_ERROR;
2840Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
2850Sstevel@tonic-gate sev = MM_HALT;
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, sev, msg);
2880Sstevel@tonic-gate halt = TRUE;
2890Sstevel@tonic-gate }
2900Sstevel@tonic-gate else if (errno == EPERM) {
2910Sstevel@tonic-gate
2920Sstevel@tonic-gate /* Wrong key */
2930Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_NOTONKEY, *argp);
2940Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
2950Sstevel@tonic-gate exitcode = EX_NOFREE;
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate else if (errno == EINVAL) {
2980Sstevel@tonic-gate
2990Sstevel@tonic-gate /* Device not reserved */
3000Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), M_NOTRSVD, *argp);
3010Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
3020Sstevel@tonic-gate exitcode = EX_NOFREE;
3030Sstevel@tonic-gate }
3040Sstevel@tonic-gate
3050Sstevel@tonic-gate else {
3060Sstevel@tonic-gate
3070Sstevel@tonic-gate /* Some other strange error occurred */
3080Sstevel@tonic-gate (void) snprintf(msg, sizeof (msg), M_ERROR, errno);
3090Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_HALT, msg);
3100Sstevel@tonic-gate exitcode = EX_ERROR;
3110Sstevel@tonic-gate halt = TRUE;
3120Sstevel@tonic-gate }
3130Sstevel@tonic-gate }
3140Sstevel@tonic-gate argp++;
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate
3170Sstevel@tonic-gate
3180Sstevel@tonic-gate /* Exit with the appropriate code */
3190Sstevel@tonic-gate return(exitcode);
3200Sstevel@tonic-gate }
321