OpenSolaris_b135/cmd/devmgmt/cmds/putdgrp.c

Compare this file to the similar file:
Show the results in this format:

/*
 * 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 2005 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"

/*
 *	Implements the "putdgrp" command.
 */
#include	<sys/types.h>
#include	<stdio.h>
#include	<stdlib.h>
#include	<string.h>
#include	<errno.h>
#include	<unistd.h>
#include	<fmtmsg.h>
#include	<devmgmt.h>
#include	<devtab.h>


/*
 * General Purpose Constants
 *	TRUE		Boolean TRUE (if not already defined)
 *	FALSE		Boolean FALSE (if not already defined)
 */

#ifndef	TRUE
#define	TRUE	(1)
#endif

#ifndef	FALSE
#define	FALSE	(0)
#endif

/*
 * Exit codes
 *	EX_OK		All went well
 *	EX_ERROR	Usage or internal error 
 *	EX_DGROUP	Had trouble accessing/reading/writing the 
 *			device-group table
 *	EX_NODGRP	The specified device-group does not exist
 *	EX_NOMEM	One or more device-group members requested for 
 *			removal was not defined for the device
 */

#define	EX_OK		0
#define	EX_ERROR	1
#define	EX_DGROUP	2
#define	EX_NODGRP	3
#define	EX_NOMEM	4


/*
 * Error messages
 */

#define	E_USAGE		"usage: putdgrp [-d] dgroup [device [...]]"
#define	E_NODGRP	"Device-group does not exist in table: %s"
#define	E_NOTAMEM	"Device-group member not found: %s"
#define	E_NODGRPTAB	"Cannot open the device-group table: %s"
#define	E_NOMKTAB	"Cannot create a new device-group table: %s"
#define	E_INTERNAL	"Internal error, errno=%d"


/*
 * Macros
 *	stdmsg(r,l,s,t)	    Using fmtmsg(), write a standard message to the
 *			    standard error stream.
 *			    Where:
 *				r   The recoverability of the error
 *				l   The label-component
 *				s   The severity-component
 *				t   The text-component
 */

#define stdmsg(r,l,s,t) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,t,MM_NULLACT,MM_NULLTAG)


/*
 * Static data
 *	msg		Space for message's text-component
 */

static	char		msg[256];	/* Space for text of message */

/*
 * char *mklbl(cmd)
 *	char   *cmd
 *
 *	This function builds a standard label from the command used to invoke
 *	this process and the standard label prefix ("UX:")
 *
 * Arguments:
 *	char *cmd	The command used to invoke this process.
 *
 * Returns:  char *
 *	Pointer to malloc()ed space containing the standard label,
 *	or (char *) NULL if an error occurred.
 */
  
static char *
mklbl(cmd)
	char   *cmd;
{
	/* Automatic data */
	char   *rtn;		/* Value to return */
	char   *p;		/* Temporary */

	/* Find the 1st char of the basename of the command */
	if (p = strrchr(cmd, '/')) p++;
	else p = cmd;

	/* Allocate and build the string value to return */
	if (rtn = (char *) malloc(strlen("UX:")+strlen(p)+1)) {
	    (void) strcpy(rtn, "UX:");
	    (void) strcat(rtn, p);
	}

	/* Now that we've done all of this work, set up the environemnt
	 * so that only the text-component is written (some requirements
	 * say that standard messages are to be non-standard in SVR4.0,
	 * this is supposed to change in SVR4.1)
	 */

	(void) putenv("MSGVERB=text");

	/* Done */
	return(rtn);
}

/*
 * putdgrp [-d] dgroup [device [...]]
 *
 * Options:
 *	-d		
 *
 * Arguments:
 *	dgroup
 *	device
 *
 * Exit values:
 */

int
main(int argc, char *argv[])
{
	/* Automatic data */
	char	      **plist;		/* Ptr to list of nonmembers */
	char	       *lbl;		/* Ptr to label for messages */
	char	       *dgroup;		/* Ptr to <dgroup> on command-line */
	char	       *p;		/* Temp ptr to char */
	int		noerr;		/* FLAG, TRUE if all's well */
	int		d_seen;		/* TRUE if -a seen on command-line */
	int		optchar;	/* Option extracted */
	int		exitcd;		/* Value to return at exit */
	int		nmems;		/* Number of members on the cmd */

	
	/* Generate the label for messages */
	lbl = mklbl(argv[0]);

	/* Extract arguments - validate usage */
	noerr = TRUE;
	d_seen = FALSE;
	opterr = FALSE;
	while ((optchar = getopt(argc, argv, "d:")) != EOF) switch (optchar) {

	case 'd':
	    if (!d_seen) 
	    {
		d_seen = TRUE;
		dgroup = optarg;
	    }
	    else noerr = FALSE;
	    break;

	case '?':
	default:
	    noerr = FALSE;
	}


	/* Write a usage message if we've seen a blatant error */
	if (!noerr || (!d_seen && ((nmems = argc - optind - 1) < 0)) || 
		      (d_seen && ((nmems = argc - optind) < 0))) {
	    stdmsg(MM_NRECOV, lbl, MM_ERROR, E_USAGE);
	    exit(EX_ERROR);
	}


	/* Set up */
	exitcd = EX_OK;


	/* -d on the command line ? */
	if (d_seen) {

	    /* 
	     * Determine case (removing a device group or members
	     * of that device group.
	     */

	    if (nmems == 0) {

		/* putdgrp -d dgroup */

		/* Attempt to remove the specified device */
		if (!(_rmdgrptabrec(dgroup))) switch(errno) {

		    /*
		     * EINVAL indicates that the named device-group was
		     * not found in the device-group table.
		     */

		case EINVAL:
		    (void) snprintf(msg, sizeof(msg), E_NODGRP, dgroup);
		    stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
		    exitcd = EX_NODGRP;
		    break;

		    /*
		     * ENOENT indicates that the device-group table can't
		     * be found.
		     */

		case ENOENT:
		    (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath());
		    stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
		    exitcd = EX_DGROUP; 
		    break;

		    /*
		     * EACCES indicates that there was a problem reading the 
		     * old device-group table or creating the new table.  If the
		     * old table is readable, assume that we can't create the
		     * new table.  Otherwise, assume that the old table isn't
		     * accessible.
		     */

		case EACCES:
		    p = _dgrptabpath();
		    if (access(p, R_OK) == 0) 
			(void) snprintf(msg, sizeof(msg), E_NOMKTAB, p);
		    else 
			(void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p);
		    stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
		    exitcd = EX_DGROUP; 
		    break;

		    /*
		     * Some strange problem...
		     */

		default:
		    (void) snprintf(msg, sizeof(msg), E_INTERNAL, errno);
		    stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
		    exitcd = EX_ERROR;

		}   /* End switch */
	    }
	    else {

		/* putdgrp -d dgroup device [device [...]] */

		/* 
		 * Attempt to remove the specified devices from the
		 * specified device-group.
		 */
		if (!(_rmdgrpmems(dgroup, &argv[optind], &plist))) switch(errno) {

		    /*
		     * ENODEV indicates that a named device was not part
		     * of the specified device group.
		     */

		case ENODEV:
		    exitcd = EX_NOMEM;
		    for (; *plist; plist++) {
			(void) snprintf(msg, sizeof(msg), E_NOTAMEM, *plist);
			stdmsg(MM_RECOVER, lbl, MM_WARNING, msg);
		    }
		    break;

		    /*
		     * EINVAL indicates that the named device-group is not 
		     * defined in the device-group table.
		     */

		case EINVAL:
		    (void) snprintf(msg, sizeof(msg), E_NODGRP, dgroup);
		    stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
		    exitcd = EX_NODGRP;
		    break;

		    /*
		     * ENOENT indicates that the device table can't
		     * be found.
		     */

		case ENOENT:
		    (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath());
		    stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
		    exitcd = EX_DGROUP; 
		    break;

		    /*
		     * EACCES indicates that there was a problem reading the 
		     * old device table or creating the new table.  If the
		     * old table is readable, assume that we can't create the
		     * new table.  Otherwise, assume that the old table isn't
		     * accessible.
		     */

		case EACCES:
		    p = _dgrptabpath();
		    if (access(p, R_OK) == 0) 
			(void) snprintf(msg, sizeof(msg), E_NOMKTAB, p);
		    else 
			(void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p);
		    stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
		    exitcd = EX_DGROUP; 
		    break;

		    /*
		     * Some strange problem...
		     */

		default:
		    (void) sprintf(msg, E_INTERNAL, errno);
		    stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
		    exitcd = EX_ERROR;

		}  /* End switch */

	    }   /* End "putdgrp -d device attr [...]" case */


	}   /* End -d case */

	else {
	    /* Standard case (no -d on the command) */
	    if (!(_adddgrptabrec(argv[optind], &argv[optind+1]))) switch(errno) {

		/*
		 * ENOENT indicates that the device-group table does not exist.
		 */

	    case ENOENT:
		(void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath());
		stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
		exitcd = EX_DGROUP; 
		break;

		/*
		 * EACCES indicates that the device-group table could not be
		 * opened or the new device-group table could not be created.
		 */

	    case EACCES:
		p = _dgrptabpath();
		if (access(p, R_OK) == 0)
			(void) snprintf(msg, sizeof(msg), E_NOMKTAB, p);
		else
			(void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p);
		stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
		exitcd = EX_DGROUP; 
		break;

		/* 
		 * Some strange error (memory?) 
		 */

	    default:
		(void) sprintf(msg, E_INTERNAL, errno);
		stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
		exitcd = EX_ERROR;
	    }
	}

	/* Done.  Return exit code (determined above) */
	return(exitcd);
}  /* main() */