devfree.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2003 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* devfree key [device [...]]
*/
#include <sys/types.h>
#include <sys/param.h>
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <fmtmsg.h>
#include <devmgmt.h>
#include <values.h>
#include <devtab.h>
/*
* Local definitions
* TRUE Boolean TRUE value
* FALSE Boolean FALSE value
*/
#ifndef TRUE
#define TRUE ('t')
#endif
#ifndef FALSE
#define FALSE 0
#endif
/*
* Exit codes:
* EX_OK Exit code for all went well
* EX_ERROR Exit code for something failed
* EX_TBLERR Exit code for errors relating to device or lock tables
* EX_NOFREE Exit code for free failed
*/
#define EX_OK 0
#define EX_ERROR 1
#define EX_TBLERR 2
#define EX_NOFREE 3
/*
* Messages
* M_USAGE Usage error
* M_INVKEY Invalid key specified
* M_NOTRSVD Attempting to free something not alloc'd
* M_NOTONKEY Attempting to free with wrong key
* M_DEVTAB Error opening the device table
* M_RSVTAB Error opening the device-reservation table
* M_ERROR Some internal error
*/
#define M_USAGE "usage: devfree key [device [...]]"
#define M_INVKEY "Invalid key: %s"
#define M_NOTRSVD "Device not reserved: %s"
#define M_NOTONKEY "Cannot unreserve device: %s"
#define M_DEVTAB "Cannot open the device table: %s"
#define M_RSVTAB "Cannot open the device-reservation table: %s"
#define M_ERROR "Internal error, errno=%d"
/*
* Local functions and static data
* stdmsg(r,l,s,m) Macro for standard message generation
* r MM_NRECOV or MM_RECOV (recoverability)
* l Label
* s Severity
* m Message
* lbl Buffer for the label-component of a message.
* msg Buffer for the text-component of a message.
*/
#define stdmsg(r,l,s,m) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,m,MM_NULLACT,MM_NULLTAG)
static char lbl[MM_MXLABELLN+1];
static char msg[MM_MXTXTLN+1];
/*
* devfree key [device [device [...]]]
*
* This command frees devices that have been reserved using
* the devreserv command (or the devreserv() function).
*
* Options: None
*
* Arguments:
* key The key on which the device to free was allocated on.
* If omitted, all keys are assumed.
* device The device to free. If omitted, all devices allocated
* using the key are freed.
*
* Command Values:
* EX_OK 0 Device(s) successfully freed
* EX_ERROR 1 A syntax error or other error occurred
* EX_TBLERR 2 A problem with device management tables
* EX_NOFREE 3 A requested device couldn't be freed
*/
main(argc, argv)
int argc; /* Arg count */
char *argv[]; /* Arg vector */
{
/* Automatics */
char **argp; /* Ptr to current argument */
struct reservdev **rsvd; /* Ptr to list of locks */
struct reservdev **plk; /* Running ptr to locks */
char *devtab; /* Ptr to device table name */
char *rsvtab; /* Ptr to dev-rsv-tbl name */
char *p; /* Temp char pointer */
int argcount; /* Number of args on cmd */
long lkey; /* Key for locking (long) */
int key; /* Key for locking */
int halt; /* TRUE if we need to stop */
int sev; /* Message severity */
int exitcode; /* Value of command */
int syntaxerr; /* Flag, TRUE if syntax error */
int exitcd; /* Value for exit() */
int c; /* Option character */
/*
* Initializations
*/
/* Build a message label */
if (p = strrchr(argv[0], '/')) p++;
else p = argv[0];
(void) strlcat(strcpy(lbl, "UX:"), p, sizeof(lbl));
/* Make only the text component of messages appear (remove this in SVR4.1) */
(void) putenv("MSGVERB=text");
/*
* Parse the options from the command line
*/
opterr = 0;
syntaxerr = FALSE;
while ((c = getopt(argc, argv, "")) != EOF) switch(c) {
default:
syntaxerr = FALSE;
break;
}
/* Argument initializations */
argp = &argv[optind];
if ((argcount = argc-optind) < 1) syntaxerr = TRUE;
/* If there's (an obvious) syntax error, write a message and quit */
if (syntaxerr) {
stdmsg(MM_NRECOV, lbl, MM_ERROR, M_USAGE);
exit(EX_ERROR);
}
/*
* devfree key
*
* Free all devices that have been reserved using the key "key".
*/
if (argcount == 1) {
/* Extract the key from the command */
lkey = strtol(*argp, &p, 10);
if (*p || (lkey <= 0) || (lkey > MAXINT)) {
(void) snprintf(msg, sizeof (msg), M_INVKEY, *argp);
stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
exit(EX_ERROR);
}
key = (int) lkey;
/* Get the list of devices currently reserved */
if (rsvd = reservdev()) {
exitcd = EX_OK;
for (plk = rsvd ; *plk ; plk++) {
if ((*plk)->key == key)
if (devfree(key, (*plk)->devname) != 0)
exitcd = EX_NOFREE;
}
} else {
if (((errno == ENOENT) || (errno == EACCES)) && (rsvtab = _rsvtabpath())) {
(void) snprintf(msg, sizeof(msg), M_RSVTAB, rsvtab);
exitcd = EX_TBLERR;
sev = MM_ERROR;
} else {
(void) snprintf(msg, sizeof (msg), M_ERROR, errno);
exitcd = EX_ERROR;
sev = MM_HALT;
}
stdmsg(MM_NRECOV, lbl, sev, msg);
}
/* Done */
exit(exitcd);
}
/*
* devfree key device [...]
*
* Free specific devices
*/
/* Open the device file (if there's one to be opened) */
if (!_opendevtab("r")) {
if (devtab = _devtabpath()) {
(void) snprintf(msg, sizeof(msg), M_DEVTAB, devtab);
exitcd = EX_TBLERR;
sev = MM_ERROR;
} else {
(void) snprintf(msg, sizeof (msg), M_ERROR, errno);
exitcd = EX_ERROR;
sev = MM_HALT;
}
stdmsg(MM_NRECOV, lbl, sev, msg);
exit(exitcd);
}
/* Extract the key from the command */
lkey = strtol(*argp, &p, 10);
if (*p || (lkey <= 0) || (lkey > MAXINT)) {
(void) snprintf(msg, sizeof(msg), M_INVKEY, *argp);
stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
exit(EX_ERROR);
}
key = (int) lkey;
argp++;
/* Loop through the list of devices to free */
exitcode = EX_OK;
halt = FALSE;
while (!halt && *argp) {
/* Try to free the device */
if (devfree(key, *argp) != 0) {
if ((errno == EACCES) || (errno == ENOENT)) {
/* Can't get at reservation file */
if (rsvtab = _rsvtabpath()) {
exitcode = EX_TBLERR;
(void) snprintf(msg, sizeof(msg), M_RSVTAB, rsvtab);
sev = MM_ERROR;
}
else {
exitcode = EX_ERROR;
(void) snprintf(msg, sizeof (msg), M_ERROR, errno);
sev = MM_HALT;
}
stdmsg(MM_NRECOV, lbl, sev, msg);
halt = TRUE;
}
else if (errno == EPERM) {
/* Wrong key */
(void) snprintf(msg, sizeof(msg), M_NOTONKEY, *argp);
stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
exitcode = EX_NOFREE;
}
else if (errno == EINVAL) {
/* Device not reserved */
(void) snprintf(msg, sizeof(msg), M_NOTRSVD, *argp);
stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
exitcode = EX_NOFREE;
}
else {
/* Some other strange error occurred */
(void) snprintf(msg, sizeof (msg), M_ERROR, errno);
stdmsg(MM_NRECOV, lbl, MM_HALT, msg);
exitcode = EX_ERROR;
halt = TRUE;
}
}
argp++;
}
/* Exit with the appropriate code */
return(exitcode);
}