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 * Implements the "putdgrp" command.
350Sstevel@tonic-gate */
360Sstevel@tonic-gate #include <sys/types.h>
370Sstevel@tonic-gate #include <stdio.h>
380Sstevel@tonic-gate #include <stdlib.h>
390Sstevel@tonic-gate #include <string.h>
400Sstevel@tonic-gate #include <errno.h>
410Sstevel@tonic-gate #include <unistd.h>
420Sstevel@tonic-gate #include <fmtmsg.h>
430Sstevel@tonic-gate #include <devmgmt.h>
440Sstevel@tonic-gate #include <devtab.h>
450Sstevel@tonic-gate
460Sstevel@tonic-gate
470Sstevel@tonic-gate /*
480Sstevel@tonic-gate * General Purpose Constants
490Sstevel@tonic-gate * TRUE Boolean TRUE (if not already defined)
500Sstevel@tonic-gate * FALSE Boolean FALSE (if not already defined)
510Sstevel@tonic-gate */
520Sstevel@tonic-gate
530Sstevel@tonic-gate #ifndef TRUE
540Sstevel@tonic-gate #define TRUE (1)
550Sstevel@tonic-gate #endif
560Sstevel@tonic-gate
570Sstevel@tonic-gate #ifndef FALSE
580Sstevel@tonic-gate #define FALSE (0)
590Sstevel@tonic-gate #endif
600Sstevel@tonic-gate
610Sstevel@tonic-gate /*
620Sstevel@tonic-gate * Exit codes
630Sstevel@tonic-gate * EX_OK All went well
640Sstevel@tonic-gate * EX_ERROR Usage or internal error
650Sstevel@tonic-gate * EX_DGROUP Had trouble accessing/reading/writing the
660Sstevel@tonic-gate * device-group table
670Sstevel@tonic-gate * EX_NODGRP The specified device-group does not exist
680Sstevel@tonic-gate * EX_NOMEM One or more device-group members requested for
690Sstevel@tonic-gate * removal was not defined for the device
700Sstevel@tonic-gate */
710Sstevel@tonic-gate
720Sstevel@tonic-gate #define EX_OK 0
730Sstevel@tonic-gate #define EX_ERROR 1
740Sstevel@tonic-gate #define EX_DGROUP 2
750Sstevel@tonic-gate #define EX_NODGRP 3
760Sstevel@tonic-gate #define EX_NOMEM 4
770Sstevel@tonic-gate
780Sstevel@tonic-gate
790Sstevel@tonic-gate /*
800Sstevel@tonic-gate * Error messages
810Sstevel@tonic-gate */
820Sstevel@tonic-gate
830Sstevel@tonic-gate #define E_USAGE "usage: putdgrp [-d] dgroup [device [...]]"
840Sstevel@tonic-gate #define E_NODGRP "Device-group does not exist in table: %s"
850Sstevel@tonic-gate #define E_NOTAMEM "Device-group member not found: %s"
860Sstevel@tonic-gate #define E_NODGRPTAB "Cannot open the device-group table: %s"
870Sstevel@tonic-gate #define E_NOMKTAB "Cannot create a new device-group table: %s"
880Sstevel@tonic-gate #define E_INTERNAL "Internal error, errno=%d"
890Sstevel@tonic-gate
900Sstevel@tonic-gate
910Sstevel@tonic-gate /*
920Sstevel@tonic-gate * Macros
930Sstevel@tonic-gate * stdmsg(r,l,s,t) Using fmtmsg(), write a standard message to the
940Sstevel@tonic-gate * standard error stream.
950Sstevel@tonic-gate * Where:
960Sstevel@tonic-gate * r The recoverability of the error
970Sstevel@tonic-gate * l The label-component
980Sstevel@tonic-gate * s The severity-component
990Sstevel@tonic-gate * t The text-component
1000Sstevel@tonic-gate */
1010Sstevel@tonic-gate
1020Sstevel@tonic-gate #define stdmsg(r,l,s,t) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,t,MM_NULLACT,MM_NULLTAG)
1030Sstevel@tonic-gate
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate /*
1060Sstevel@tonic-gate * Static data
1070Sstevel@tonic-gate * msg Space for message's text-component
1080Sstevel@tonic-gate */
1090Sstevel@tonic-gate
1100Sstevel@tonic-gate static char msg[256]; /* Space for text of message */
1110Sstevel@tonic-gate
1120Sstevel@tonic-gate /*
1130Sstevel@tonic-gate * char *mklbl(cmd)
1140Sstevel@tonic-gate * char *cmd
1150Sstevel@tonic-gate *
1160Sstevel@tonic-gate * This function builds a standard label from the command used to invoke
1170Sstevel@tonic-gate * this process and the standard label prefix ("UX:")
1180Sstevel@tonic-gate *
1190Sstevel@tonic-gate * Arguments:
1200Sstevel@tonic-gate * char *cmd The command used to invoke this process.
1210Sstevel@tonic-gate *
1220Sstevel@tonic-gate * Returns: char *
1230Sstevel@tonic-gate * Pointer to malloc()ed space containing the standard label,
1240Sstevel@tonic-gate * or (char *) NULL if an error occurred.
1250Sstevel@tonic-gate */
1260Sstevel@tonic-gate
1270Sstevel@tonic-gate static char *
mklbl(cmd)1280Sstevel@tonic-gate mklbl(cmd)
1290Sstevel@tonic-gate char *cmd;
1300Sstevel@tonic-gate {
1310Sstevel@tonic-gate /* Automatic data */
1320Sstevel@tonic-gate char *rtn; /* Value to return */
1330Sstevel@tonic-gate char *p; /* Temporary */
1340Sstevel@tonic-gate
1350Sstevel@tonic-gate /* Find the 1st char of the basename of the command */
1360Sstevel@tonic-gate if (p = strrchr(cmd, '/')) p++;
1370Sstevel@tonic-gate else p = cmd;
1380Sstevel@tonic-gate
1390Sstevel@tonic-gate /* Allocate and build the string value to return */
1400Sstevel@tonic-gate if (rtn = (char *) malloc(strlen("UX:")+strlen(p)+1)) {
1410Sstevel@tonic-gate (void) strcpy(rtn, "UX:");
1420Sstevel@tonic-gate (void) strcat(rtn, p);
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate
1450Sstevel@tonic-gate /* Now that we've done all of this work, set up the environemnt
1460Sstevel@tonic-gate * so that only the text-component is written (some requirements
1470Sstevel@tonic-gate * say that standard messages are to be non-standard in SVR4.0,
1480Sstevel@tonic-gate * this is supposed to change in SVR4.1)
1490Sstevel@tonic-gate */
1500Sstevel@tonic-gate
1510Sstevel@tonic-gate (void) putenv("MSGVERB=text");
1520Sstevel@tonic-gate
1530Sstevel@tonic-gate /* Done */
1540Sstevel@tonic-gate return(rtn);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate
1570Sstevel@tonic-gate /*
1580Sstevel@tonic-gate * putdgrp [-d] dgroup [device [...]]
1590Sstevel@tonic-gate *
1600Sstevel@tonic-gate * Options:
1610Sstevel@tonic-gate * -d
1620Sstevel@tonic-gate *
1630Sstevel@tonic-gate * Arguments:
1640Sstevel@tonic-gate * dgroup
1650Sstevel@tonic-gate * device
1660Sstevel@tonic-gate *
1670Sstevel@tonic-gate * Exit values:
1680Sstevel@tonic-gate */
1690Sstevel@tonic-gate
170*644Sakaplan int
main(int argc,char * argv[])171*644Sakaplan main(int argc, char *argv[])
1720Sstevel@tonic-gate {
1730Sstevel@tonic-gate /* Automatic data */
1740Sstevel@tonic-gate char **plist; /* Ptr to list of nonmembers */
1750Sstevel@tonic-gate char *lbl; /* Ptr to label for messages */
1760Sstevel@tonic-gate char *dgroup; /* Ptr to <dgroup> on command-line */
1770Sstevel@tonic-gate char *p; /* Temp ptr to char */
1780Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */
1790Sstevel@tonic-gate int d_seen; /* TRUE if -a seen on command-line */
1800Sstevel@tonic-gate int optchar; /* Option extracted */
1810Sstevel@tonic-gate int exitcd; /* Value to return at exit */
1820Sstevel@tonic-gate int nmems; /* Number of members on the cmd */
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate
1850Sstevel@tonic-gate /* Generate the label for messages */
1860Sstevel@tonic-gate lbl = mklbl(argv[0]);
1870Sstevel@tonic-gate
1880Sstevel@tonic-gate /* Extract arguments - validate usage */
1890Sstevel@tonic-gate noerr = TRUE;
1900Sstevel@tonic-gate d_seen = FALSE;
1910Sstevel@tonic-gate opterr = FALSE;
1920Sstevel@tonic-gate while ((optchar = getopt(argc, argv, "d:")) != EOF) switch (optchar) {
1930Sstevel@tonic-gate
1940Sstevel@tonic-gate case 'd':
1950Sstevel@tonic-gate if (!d_seen)
1960Sstevel@tonic-gate {
1970Sstevel@tonic-gate d_seen = TRUE;
1980Sstevel@tonic-gate dgroup = optarg;
1990Sstevel@tonic-gate }
2000Sstevel@tonic-gate else noerr = FALSE;
2010Sstevel@tonic-gate break;
2020Sstevel@tonic-gate
2030Sstevel@tonic-gate case '?':
2040Sstevel@tonic-gate default:
2050Sstevel@tonic-gate noerr = FALSE;
2060Sstevel@tonic-gate }
2070Sstevel@tonic-gate
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate /* Write a usage message if we've seen a blatant error */
2100Sstevel@tonic-gate if (!noerr || (!d_seen && ((nmems = argc - optind - 1) < 0)) ||
2110Sstevel@tonic-gate (d_seen && ((nmems = argc - optind) < 0))) {
2120Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, E_USAGE);
2130Sstevel@tonic-gate exit(EX_ERROR);
2140Sstevel@tonic-gate }
2150Sstevel@tonic-gate
2160Sstevel@tonic-gate
2170Sstevel@tonic-gate /* Set up */
2180Sstevel@tonic-gate exitcd = EX_OK;
2190Sstevel@tonic-gate
2200Sstevel@tonic-gate
2210Sstevel@tonic-gate /* -d on the command line ? */
2220Sstevel@tonic-gate if (d_seen) {
2230Sstevel@tonic-gate
2240Sstevel@tonic-gate /*
2250Sstevel@tonic-gate * Determine case (removing a device group or members
2260Sstevel@tonic-gate * of that device group.
2270Sstevel@tonic-gate */
2280Sstevel@tonic-gate
2290Sstevel@tonic-gate if (nmems == 0) {
2300Sstevel@tonic-gate
2310Sstevel@tonic-gate /* putdgrp -d dgroup */
2320Sstevel@tonic-gate
2330Sstevel@tonic-gate /* Attempt to remove the specified device */
2340Sstevel@tonic-gate if (!(_rmdgrptabrec(dgroup))) switch(errno) {
2350Sstevel@tonic-gate
2360Sstevel@tonic-gate /*
2370Sstevel@tonic-gate * EINVAL indicates that the named device-group was
2380Sstevel@tonic-gate * not found in the device-group table.
2390Sstevel@tonic-gate */
2400Sstevel@tonic-gate
2410Sstevel@tonic-gate case EINVAL:
2420Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODGRP, dgroup);
2430Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
2440Sstevel@tonic-gate exitcd = EX_NODGRP;
2450Sstevel@tonic-gate break;
2460Sstevel@tonic-gate
2470Sstevel@tonic-gate /*
2480Sstevel@tonic-gate * ENOENT indicates that the device-group table can't
2490Sstevel@tonic-gate * be found.
2500Sstevel@tonic-gate */
2510Sstevel@tonic-gate
2520Sstevel@tonic-gate case ENOENT:
2530Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath());
2540Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
2550Sstevel@tonic-gate exitcd = EX_DGROUP;
2560Sstevel@tonic-gate break;
2570Sstevel@tonic-gate
2580Sstevel@tonic-gate /*
2590Sstevel@tonic-gate * EACCES indicates that there was a problem reading the
2600Sstevel@tonic-gate * old device-group table or creating the new table. If the
2610Sstevel@tonic-gate * old table is readable, assume that we can't create the
2620Sstevel@tonic-gate * new table. Otherwise, assume that the old table isn't
2630Sstevel@tonic-gate * accessible.
2640Sstevel@tonic-gate */
2650Sstevel@tonic-gate
2660Sstevel@tonic-gate case EACCES:
2670Sstevel@tonic-gate p = _dgrptabpath();
2680Sstevel@tonic-gate if (access(p, R_OK) == 0)
2690Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p);
2700Sstevel@tonic-gate else
2710Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p);
2720Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
2730Sstevel@tonic-gate exitcd = EX_DGROUP;
2740Sstevel@tonic-gate break;
2750Sstevel@tonic-gate
2760Sstevel@tonic-gate /*
2770Sstevel@tonic-gate * Some strange problem...
2780Sstevel@tonic-gate */
2790Sstevel@tonic-gate
2800Sstevel@tonic-gate default:
2810Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_INTERNAL, errno);
2820Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
2830Sstevel@tonic-gate exitcd = EX_ERROR;
2840Sstevel@tonic-gate
2850Sstevel@tonic-gate } /* End switch */
2860Sstevel@tonic-gate }
2870Sstevel@tonic-gate else {
2880Sstevel@tonic-gate
2890Sstevel@tonic-gate /* putdgrp -d dgroup device [device [...]] */
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate /*
2920Sstevel@tonic-gate * Attempt to remove the specified devices from the
2930Sstevel@tonic-gate * specified device-group.
2940Sstevel@tonic-gate */
2950Sstevel@tonic-gate if (!(_rmdgrpmems(dgroup, &argv[optind], &plist))) switch(errno) {
2960Sstevel@tonic-gate
2970Sstevel@tonic-gate /*
2980Sstevel@tonic-gate * ENODEV indicates that a named device was not part
2990Sstevel@tonic-gate * of the specified device group.
3000Sstevel@tonic-gate */
3010Sstevel@tonic-gate
3020Sstevel@tonic-gate case ENODEV:
3030Sstevel@tonic-gate exitcd = EX_NOMEM;
3040Sstevel@tonic-gate for (; *plist; plist++) {
3050Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NOTAMEM, *plist);
3060Sstevel@tonic-gate stdmsg(MM_RECOVER, lbl, MM_WARNING, msg);
3070Sstevel@tonic-gate }
3080Sstevel@tonic-gate break;
3090Sstevel@tonic-gate
3100Sstevel@tonic-gate /*
3110Sstevel@tonic-gate * EINVAL indicates that the named device-group is not
3120Sstevel@tonic-gate * defined in the device-group table.
3130Sstevel@tonic-gate */
3140Sstevel@tonic-gate
3150Sstevel@tonic-gate case EINVAL:
3160Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODGRP, dgroup);
3170Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
3180Sstevel@tonic-gate exitcd = EX_NODGRP;
3190Sstevel@tonic-gate break;
3200Sstevel@tonic-gate
3210Sstevel@tonic-gate /*
3220Sstevel@tonic-gate * ENOENT indicates that the device table can't
3230Sstevel@tonic-gate * be found.
3240Sstevel@tonic-gate */
3250Sstevel@tonic-gate
3260Sstevel@tonic-gate case ENOENT:
3270Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath());
3280Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
3290Sstevel@tonic-gate exitcd = EX_DGROUP;
3300Sstevel@tonic-gate break;
3310Sstevel@tonic-gate
3320Sstevel@tonic-gate /*
3330Sstevel@tonic-gate * EACCES indicates that there was a problem reading the
3340Sstevel@tonic-gate * old device table or creating the new table. If the
3350Sstevel@tonic-gate * old table is readable, assume that we can't create the
3360Sstevel@tonic-gate * new table. Otherwise, assume that the old table isn't
3370Sstevel@tonic-gate * accessible.
3380Sstevel@tonic-gate */
3390Sstevel@tonic-gate
3400Sstevel@tonic-gate case EACCES:
3410Sstevel@tonic-gate p = _dgrptabpath();
3420Sstevel@tonic-gate if (access(p, R_OK) == 0)
3430Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p);
3440Sstevel@tonic-gate else
3450Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p);
3460Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
3470Sstevel@tonic-gate exitcd = EX_DGROUP;
3480Sstevel@tonic-gate break;
3490Sstevel@tonic-gate
3500Sstevel@tonic-gate /*
3510Sstevel@tonic-gate * Some strange problem...
3520Sstevel@tonic-gate */
3530Sstevel@tonic-gate
3540Sstevel@tonic-gate default:
3550Sstevel@tonic-gate (void) sprintf(msg, E_INTERNAL, errno);
3560Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
3570Sstevel@tonic-gate exitcd = EX_ERROR;
3580Sstevel@tonic-gate
3590Sstevel@tonic-gate } /* End switch */
3600Sstevel@tonic-gate
3610Sstevel@tonic-gate } /* End "putdgrp -d device attr [...]" case */
3620Sstevel@tonic-gate
3630Sstevel@tonic-gate
3640Sstevel@tonic-gate } /* End -d case */
3650Sstevel@tonic-gate
3660Sstevel@tonic-gate else {
3670Sstevel@tonic-gate /* Standard case (no -d on the command) */
3680Sstevel@tonic-gate if (!(_adddgrptabrec(argv[optind], &argv[optind+1]))) switch(errno) {
3690Sstevel@tonic-gate
3700Sstevel@tonic-gate /*
3710Sstevel@tonic-gate * ENOENT indicates that the device-group table does not exist.
3720Sstevel@tonic-gate */
3730Sstevel@tonic-gate
3740Sstevel@tonic-gate case ENOENT:
3750Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath());
3760Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
3770Sstevel@tonic-gate exitcd = EX_DGROUP;
3780Sstevel@tonic-gate break;
3790Sstevel@tonic-gate
3800Sstevel@tonic-gate /*
3810Sstevel@tonic-gate * EACCES indicates that the device-group table could not be
3820Sstevel@tonic-gate * opened or the new device-group table could not be created.
3830Sstevel@tonic-gate */
3840Sstevel@tonic-gate
3850Sstevel@tonic-gate case EACCES:
3860Sstevel@tonic-gate p = _dgrptabpath();
3870Sstevel@tonic-gate if (access(p, R_OK) == 0)
3880Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p);
3890Sstevel@tonic-gate else
3900Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p);
3910Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
3920Sstevel@tonic-gate exitcd = EX_DGROUP;
3930Sstevel@tonic-gate break;
3940Sstevel@tonic-gate
3950Sstevel@tonic-gate /*
3960Sstevel@tonic-gate * Some strange error (memory?)
3970Sstevel@tonic-gate */
3980Sstevel@tonic-gate
3990Sstevel@tonic-gate default:
4000Sstevel@tonic-gate (void) sprintf(msg, E_INTERNAL, errno);
4010Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg);
4020Sstevel@tonic-gate exitcd = EX_ERROR;
4030Sstevel@tonic-gate }
4040Sstevel@tonic-gate }
4050Sstevel@tonic-gate
4060Sstevel@tonic-gate /* Done. Return exit code (determined above) */
4070Sstevel@tonic-gate return(exitcd);
4080Sstevel@tonic-gate } /* main() */
409