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 "putdev" 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 * NULL Null address (if not already defined) 520Sstevel@tonic-gate */ 530Sstevel@tonic-gate 540Sstevel@tonic-gate #ifndef TRUE 550Sstevel@tonic-gate #define TRUE (1) 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 * Exit codes 640Sstevel@tonic-gate * EX_OK All went well 650Sstevel@tonic-gate * EX_ERROR Usage or internal error 660Sstevel@tonic-gate * EX_DEVTAB Had trouble accessing/reading/writing the device table 670Sstevel@tonic-gate * EX_EXISTS The specified alias already exists 680Sstevel@tonic-gate * EX_ATTRIB One or more attributes requested for removal was not 690Sstevel@tonic-gate * defined for the device 700Sstevel@tonic-gate * EX_RELPATH Pathname supplied for cdevice, bdevice or pathname 710Sstevel@tonic-gate * attributes was not a full pathname 720Sstevel@tonic-gate */ 730Sstevel@tonic-gate 740Sstevel@tonic-gate #define EX_OK 0 750Sstevel@tonic-gate #define EX_ERROR 1 760Sstevel@tonic-gate #define EX_DEVTAB 2 770Sstevel@tonic-gate #define EX_EXISTS 3 780Sstevel@tonic-gate #define EX_ATTRIB 4 790Sstevel@tonic-gate #define EX_RELPATH 4 800Sstevel@tonic-gate 810Sstevel@tonic-gate 820Sstevel@tonic-gate /* 830Sstevel@tonic-gate * Error messages 840Sstevel@tonic-gate */ 850Sstevel@tonic-gate 860Sstevel@tonic-gate #define E_USAGE "usage: putdev -a alias [attribute=value [...]]\n putdev -m device attribute=value [attribute=value [...]]\n putdev -d device [attribute [...]]" 870Sstevel@tonic-gate #define E_ALIASIS "Alias already exists in table: %s" 880Sstevel@tonic-gate #define E_NODEV "Device does not exist in table: %s" 890Sstevel@tonic-gate #define E_NOALIAS "Cannot use \"alias\" as an attribute" 900Sstevel@tonic-gate #define E_NOATTR "Attribute not found: %s" 910Sstevel@tonic-gate #define E_NODEVTAB "Cannot open the device table: %s" 920Sstevel@tonic-gate #define E_NOMKDTAB "Cannot create a new device table: %s" 930Sstevel@tonic-gate #define E_INVALIAS "Not a valid device alias: %s" 940Sstevel@tonic-gate #define E_MULTIPLE "Multiple definitions of an attribute are not allowed." 950Sstevel@tonic-gate #define E_INTERNAL "Internal error, errno=%d" 960Sstevel@tonic-gate #define E_RELPATH "Full pathname required for cdevice,bdevice and pathname attributes." 970Sstevel@tonic-gate 980Sstevel@tonic-gate 990Sstevel@tonic-gate /* 1000Sstevel@tonic-gate * Macros 1010Sstevel@tonic-gate * stdmsg(r,l,s,t) Using fmtmsg(), write a standard message to the 1020Sstevel@tonic-gate * standard error stream. 1030Sstevel@tonic-gate * Where: 1040Sstevel@tonic-gate * r The recoverability of the error 1050Sstevel@tonic-gate * l The label-component 1060Sstevel@tonic-gate * s The severity-component 1070Sstevel@tonic-gate * t The text-component 1080Sstevel@tonic-gate */ 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate #define stdmsg(r,l,s,t) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,t,MM_NULLACT,MM_NULLTAG) 1110Sstevel@tonic-gate 1120Sstevel@tonic-gate 1130Sstevel@tonic-gate /* 1140Sstevel@tonic-gate * Static data 1150Sstevel@tonic-gate * msg Space for message's text-component 1160Sstevel@tonic-gate */ 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate static char msg[256]; /* Space for text of message */ 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate /* 1210Sstevel@tonic-gate * char *mklbl(cmd) 1220Sstevel@tonic-gate * char *cmd 1230Sstevel@tonic-gate * 1240Sstevel@tonic-gate * This function builds a standard label from the command used to invoke 1250Sstevel@tonic-gate * this process and the standard label prefix ("UX:") 1260Sstevel@tonic-gate * 1270Sstevel@tonic-gate * Arguments: 1280Sstevel@tonic-gate * char *cmd The command used to invoke this process. 1290Sstevel@tonic-gate * 1300Sstevel@tonic-gate * Returns: char * 1310Sstevel@tonic-gate * Pointer to malloc()ed space containing the standard label, 1320Sstevel@tonic-gate * or (char *) NULL if an error occurred. 1330Sstevel@tonic-gate */ 1340Sstevel@tonic-gate 1350Sstevel@tonic-gate static char * 1360Sstevel@tonic-gate mklbl(cmd) 1370Sstevel@tonic-gate char *cmd; 1380Sstevel@tonic-gate { 1390Sstevel@tonic-gate /* Automatic data */ 1400Sstevel@tonic-gate char *rtn; /* Value to return */ 1410Sstevel@tonic-gate char *p; /* Temporary */ 1420Sstevel@tonic-gate 1430Sstevel@tonic-gate /* Find the 1st char of the basename of the command */ 1440Sstevel@tonic-gate if (p = strrchr(cmd, '/')) p++; 1450Sstevel@tonic-gate else p = cmd; 1460Sstevel@tonic-gate 1470Sstevel@tonic-gate /* Allocate and build the string value to return */ 1480Sstevel@tonic-gate if (rtn = (char *) malloc(strlen("UX:")+strlen(p)+1)) { 1490Sstevel@tonic-gate (void) strcpy(rtn, "UX:"); 1500Sstevel@tonic-gate (void) strcat(rtn, p); 1510Sstevel@tonic-gate } 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate 1540Sstevel@tonic-gate /* Now that we've done all of that work, change the environment 1550Sstevel@tonic-gate * so that only the text-component is written by fmtmsg(). 1560Sstevel@tonic-gate * (This should go away in SVR4.1) 1570Sstevel@tonic-gate */ 1580Sstevel@tonic-gate 1590Sstevel@tonic-gate (void) putenv("MSGVERB=text"); 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate 1620Sstevel@tonic-gate /* Done */ 1630Sstevel@tonic-gate return(rtn); 1640Sstevel@tonic-gate } 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate /* 1670Sstevel@tonic-gate * putdev -a alias [attribute=value [...]] 1680Sstevel@tonic-gate * putdev -m alias attribute=value [attribute=value [...]] 1690Sstevel@tonic-gate * putdev -d alias [attribute [...]] 1700Sstevel@tonic-gate * 1710Sstevel@tonic-gate * Modify the device-table. If -a specified, add a record for <alias> 1720Sstevel@tonic-gate * to the table. If -m specified, modify the attributes specified for 1730Sstevel@tonic-gate * the <device> specified. If -d specified, remove the specified 1740Sstevel@tonic-gate * attributes from the specified device or remove the specified device. 1750Sstevel@tonic-gate * 1760Sstevel@tonic-gate * Options: 1770Sstevel@tonic-gate * -a Add an alias description to the device table 1780Sstevel@tonic-gate * -m Modify an existing device description 1790Sstevel@tonic-gate * -d (if no attributes specified) remove the specified 1800Sstevel@tonic-gate * device from the device table, or (if attributes 1810Sstevel@tonic-gate * specified) remove the specified attributes from 1820Sstevel@tonic-gate * the specified device. 1830Sstevel@tonic-gate * 1840Sstevel@tonic-gate * Exit values: 1850Sstevel@tonic-gate * 0 All went well 1860Sstevel@tonic-gate * 1 Usage error (includes specifying "alias" as an 1870Sstevel@tonic-gate * <attribute>) 1880Sstevel@tonic-gate * 2 The device table file could not be opened, read 1890Sstevel@tonic-gate * or modified 1900Sstevel@tonic-gate * 3 If -a, the alias already exists. Otherwise, the 1910Sstevel@tonic-gate * specified device does not exist in the table 1920Sstevel@tonic-gate * 4 One of the specified attributes did not exist 1930Sstevel@tonic-gate * for the device and therefore wasn't removed 1940Sstevel@tonic-gate */ 1950Sstevel@tonic-gate 196*644Sakaplan int 197*644Sakaplan main(int argc, char *argv[]) 1980Sstevel@tonic-gate { 1990Sstevel@tonic-gate /* Automatic data */ 2000Sstevel@tonic-gate char **plist; /* Ptr to list of undef'nd attrs */ 2010Sstevel@tonic-gate char *lbl; /* Ptr to label for messages */ 2020Sstevel@tonic-gate char *alias; /* Ptr to <alias> on command-line */ 2030Sstevel@tonic-gate char *device; /* Ptr to <device> on command-line */ 2040Sstevel@tonic-gate char *p; /* Temp ptr to char */ 2050Sstevel@tonic-gate int noerr; /* FLAG, TRUE if all's well */ 2060Sstevel@tonic-gate int a_seen; /* TRUE if -a seen on command-line */ 2070Sstevel@tonic-gate int m_seen; /* TRUE if -m seen on command-line */ 2080Sstevel@tonic-gate int d_seen; /* TRUE if -a seen on command-line */ 2090Sstevel@tonic-gate int optchar; /* Option extracted */ 2100Sstevel@tonic-gate int exitcd; /* Value to return at exit */ 2110Sstevel@tonic-gate int nattrs; /* Number of attributes on command */ 2120Sstevel@tonic-gate 2130Sstevel@tonic-gate 2140Sstevel@tonic-gate /* Generate the label for messages */ 2150Sstevel@tonic-gate lbl = mklbl(argv[0]); 2160Sstevel@tonic-gate 2170Sstevel@tonic-gate /* Extract arguments - validate usage */ 2180Sstevel@tonic-gate noerr = TRUE; 2190Sstevel@tonic-gate a_seen = FALSE; 2200Sstevel@tonic-gate m_seen = FALSE; 2210Sstevel@tonic-gate d_seen = FALSE; 2220Sstevel@tonic-gate opterr = FALSE; 2230Sstevel@tonic-gate while ((optchar = getopt(argc, argv, "a:d:m:")) != EOF) switch (optchar) { 2240Sstevel@tonic-gate 2250Sstevel@tonic-gate case 'a': 2260Sstevel@tonic-gate if (!(a_seen || m_seen || d_seen)) { 2270Sstevel@tonic-gate a_seen = TRUE; 2280Sstevel@tonic-gate alias = optarg; 2290Sstevel@tonic-gate } 2300Sstevel@tonic-gate else noerr = FALSE; 2310Sstevel@tonic-gate break; 2320Sstevel@tonic-gate 2330Sstevel@tonic-gate case 'd': 2340Sstevel@tonic-gate if (!(a_seen || m_seen || d_seen)) { 2350Sstevel@tonic-gate d_seen = TRUE; 2360Sstevel@tonic-gate device = optarg; 2370Sstevel@tonic-gate } 2380Sstevel@tonic-gate else noerr = FALSE; 2390Sstevel@tonic-gate break; 2400Sstevel@tonic-gate 2410Sstevel@tonic-gate case 'm': 2420Sstevel@tonic-gate if (!(a_seen || m_seen || d_seen)) { 2430Sstevel@tonic-gate m_seen = TRUE; 2440Sstevel@tonic-gate device = optarg; 2450Sstevel@tonic-gate } 2460Sstevel@tonic-gate else noerr = FALSE; 2470Sstevel@tonic-gate break; 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate case '?': 2500Sstevel@tonic-gate default: 2510Sstevel@tonic-gate noerr = FALSE; 2520Sstevel@tonic-gate } 2530Sstevel@tonic-gate 2540Sstevel@tonic-gate 2550Sstevel@tonic-gate /* Write a usage message if we've seen a blatant error */ 2560Sstevel@tonic-gate if (!(a_seen || m_seen || d_seen) || !noerr) { 2570Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, E_USAGE); 2580Sstevel@tonic-gate exit(EX_ERROR); 2590Sstevel@tonic-gate } 2600Sstevel@tonic-gate 2610Sstevel@tonic-gate 2620Sstevel@tonic-gate /* Set up */ 2630Sstevel@tonic-gate exitcd = EX_OK; 2640Sstevel@tonic-gate nattrs = argc - optind; 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate 2670Sstevel@tonic-gate /* putdev -a alias [attr=value [...]] */ 2680Sstevel@tonic-gate 2690Sstevel@tonic-gate if (a_seen) { 2700Sstevel@tonic-gate 2710Sstevel@tonic-gate /* Syntax check */ 2720Sstevel@tonic-gate if (nattrs < 0) { 2730Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, E_USAGE); 2740Sstevel@tonic-gate exitcd = EX_ERROR; 2750Sstevel@tonic-gate } else { 2760Sstevel@tonic-gate 2770Sstevel@tonic-gate /* Attempt to add the new alias */ 2780Sstevel@tonic-gate if (!(_adddevtabrec(alias, &argv[optind]))) { 2790Sstevel@tonic-gate 2800Sstevel@tonic-gate /* Attempt failed. Write appropriate error message. */ 2810Sstevel@tonic-gate 2820Sstevel@tonic-gate switch(errno) { 2830Sstevel@tonic-gate 2840Sstevel@tonic-gate /* 2850Sstevel@tonic-gate * EINVAL indicates that <alias> is not valid or "alias" 2860Sstevel@tonic-gate * was mentioned as <attr> in <attr>=<value> pair. If the 2870Sstevel@tonic-gate * alias is a valid alias, assume that's the problem. 2880Sstevel@tonic-gate */ 2890Sstevel@tonic-gate 2900Sstevel@tonic-gate case EINVAL: 2910Sstevel@tonic-gate if (_validalias(alias)) 2920Sstevel@tonic-gate p = E_NOALIAS; 2930Sstevel@tonic-gate else (void) snprintf(p=msg, sizeof(msg), E_INVALIAS, alias); 2940Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, p); 2950Sstevel@tonic-gate exitcd = EX_ERROR; 2960Sstevel@tonic-gate break; 2970Sstevel@tonic-gate 2980Sstevel@tonic-gate /* 2990Sstevel@tonic-gate * EEXIST indicates that the alias <alias> already exists 3000Sstevel@tonic-gate * in the device table. 3010Sstevel@tonic-gate */ 3020Sstevel@tonic-gate 3030Sstevel@tonic-gate case EEXIST: 3040Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_ALIASIS, alias); 3050Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 3060Sstevel@tonic-gate exitcd = EX_EXISTS; 3070Sstevel@tonic-gate break; 3080Sstevel@tonic-gate 3090Sstevel@tonic-gate /* 3100Sstevel@tonic-gate * EACCES and ENOENT indicate problems reading or writing 3110Sstevel@tonic-gate * the device table. 3120Sstevel@tonic-gate */ 3130Sstevel@tonic-gate 3140Sstevel@tonic-gate case EACCES: 3150Sstevel@tonic-gate case ENOENT: 3160Sstevel@tonic-gate p = _devtabpath(); 3170Sstevel@tonic-gate if (access(p, R_OK) == 0) 3180Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NOMKDTAB, p); 3190Sstevel@tonic-gate else 3200Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODEVTAB, p); 3210Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 3220Sstevel@tonic-gate exitcd = EX_DEVTAB; 3230Sstevel@tonic-gate break; 3240Sstevel@tonic-gate 3250Sstevel@tonic-gate /* 3260Sstevel@tonic-gate * EAGAIN indicates that an attribute was defined on the 3270Sstevel@tonic-gate * command line more than once. 3280Sstevel@tonic-gate */ 3290Sstevel@tonic-gate 3300Sstevel@tonic-gate case EAGAIN: 3310Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, E_MULTIPLE); 3320Sstevel@tonic-gate exitcd = EX_ERROR; 3330Sstevel@tonic-gate break; 3340Sstevel@tonic-gate 3350Sstevel@tonic-gate /* 3360Sstevel@tonic-gate * ENXIO indicates that a relative pathname was supplied 3370Sstevel@tonic-gate * for the cdevice, bdevice or pathname attributes. Full 3380Sstevel@tonic-gate * pathnames are required for these attributes. 3390Sstevel@tonic-gate */ 3400Sstevel@tonic-gate case ENXIO: 3410Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, E_RELPATH); 3420Sstevel@tonic-gate exitcd = EX_RELPATH; 3430Sstevel@tonic-gate break; 3440Sstevel@tonic-gate 3450Sstevel@tonic-gate /* 3460Sstevel@tonic-gate * Some other problem (odd?) 3470Sstevel@tonic-gate */ 3480Sstevel@tonic-gate 3490Sstevel@tonic-gate default: 3500Sstevel@tonic-gate (void) sprintf(msg, E_INTERNAL, errno); 3510Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 3520Sstevel@tonic-gate exitcd = EX_ERROR; 3530Sstevel@tonic-gate } 3540Sstevel@tonic-gate } 3550Sstevel@tonic-gate } 3560Sstevel@tonic-gate } /* End -a case */ 3570Sstevel@tonic-gate 3580Sstevel@tonic-gate 3590Sstevel@tonic-gate /* putdev -m device attr=value [...] */ 3600Sstevel@tonic-gate 3610Sstevel@tonic-gate else if (m_seen) { 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate /* Check usage */ 3640Sstevel@tonic-gate 3650Sstevel@tonic-gate if (nattrs <= 0) { 3660Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, E_USAGE); 3670Sstevel@tonic-gate exitcd = EX_ERROR; 3680Sstevel@tonic-gate } else { 3690Sstevel@tonic-gate 3700Sstevel@tonic-gate /* Attempt to modify a device's record */ 3710Sstevel@tonic-gate if (!(_moddevtabrec(device, &argv[optind]))) { 3720Sstevel@tonic-gate 3730Sstevel@tonic-gate /* Modification attempt failed */ 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate switch(errno) { 3760Sstevel@tonic-gate 3770Sstevel@tonic-gate /* 3780Sstevel@tonic-gate * EINVAL indicates that "alias" was used as an attribute 3790Sstevel@tonic-gate * in an <attr>=<value> pair. 3800Sstevel@tonic-gate */ 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate case EINVAL: 3830Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, E_NOALIAS); 3840Sstevel@tonic-gate exitcd = EX_ERROR; 3850Sstevel@tonic-gate break; 3860Sstevel@tonic-gate 3870Sstevel@tonic-gate /* 3880Sstevel@tonic-gate * ENODEV indicates that the device that was to 3890Sstevel@tonic-gate * be modified doesn't exist. 3900Sstevel@tonic-gate */ 3910Sstevel@tonic-gate 3920Sstevel@tonic-gate case ENODEV: 3930Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODEV, device); 3940Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 3950Sstevel@tonic-gate exitcd = EX_EXISTS; 3960Sstevel@tonic-gate break; 3970Sstevel@tonic-gate 3980Sstevel@tonic-gate /* 3990Sstevel@tonic-gate * ENOENT indicates that the device-table doesn't exist. 4000Sstevel@tonic-gate */ 4010Sstevel@tonic-gate 4020Sstevel@tonic-gate case ENOENT: 4030Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODEVTAB, _devtabpath()); 4040Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 4050Sstevel@tonic-gate exitcd = EX_DEVTAB; 4060Sstevel@tonic-gate break; 4070Sstevel@tonic-gate 4080Sstevel@tonic-gate /* 4090Sstevel@tonic-gate * EACCES indicates that there was a problem reading the 4100Sstevel@tonic-gate * old device table or creating the new table. If the 4110Sstevel@tonic-gate * old table is readable, assume that we can't create the 4120Sstevel@tonic-gate * new table. Otherwise, assume that the old table isn't 4130Sstevel@tonic-gate * accessible. 4140Sstevel@tonic-gate */ 4150Sstevel@tonic-gate 4160Sstevel@tonic-gate case EACCES: 4170Sstevel@tonic-gate p = _devtabpath(); 4180Sstevel@tonic-gate if (access(p, R_OK) == 0) 4190Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NOMKDTAB, p); 4200Sstevel@tonic-gate else 4210Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODEVTAB, p); 4220Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 4230Sstevel@tonic-gate exitcd = EX_DEVTAB; 4240Sstevel@tonic-gate break; 4250Sstevel@tonic-gate 4260Sstevel@tonic-gate /* 4270Sstevel@tonic-gate * EAGAIN indicates that an attribute was specified more than 4280Sstevel@tonic-gate * once on the command line. 4290Sstevel@tonic-gate */ 4300Sstevel@tonic-gate 4310Sstevel@tonic-gate case EAGAIN: 4320Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, E_MULTIPLE); 4330Sstevel@tonic-gate exitcd = EX_ERROR; 4340Sstevel@tonic-gate break; 4350Sstevel@tonic-gate 4360Sstevel@tonic-gate /* 4370Sstevel@tonic-gate * ENXIO indicates that a relative pathname was supplied 4380Sstevel@tonic-gate * for the cdevice, bdevice or pathname attributes. Full 4390Sstevel@tonic-gate * pathnames are required for these attributes. 4400Sstevel@tonic-gate */ 4410Sstevel@tonic-gate case ENXIO: 4420Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, E_RELPATH); 4430Sstevel@tonic-gate exitcd = EX_RELPATH; 4440Sstevel@tonic-gate break; 4450Sstevel@tonic-gate 4460Sstevel@tonic-gate /* 4470Sstevel@tonic-gate * Some strange problem... 4480Sstevel@tonic-gate */ 4490Sstevel@tonic-gate 4500Sstevel@tonic-gate default: 4510Sstevel@tonic-gate (void) sprintf(msg, E_INTERNAL, errno); 4520Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 4530Sstevel@tonic-gate exitcd = EX_ERROR; 4540Sstevel@tonic-gate } 4550Sstevel@tonic-gate } 4560Sstevel@tonic-gate } 4570Sstevel@tonic-gate } /* End -m case */ 4580Sstevel@tonic-gate 4590Sstevel@tonic-gate else if (d_seen) { 4600Sstevel@tonic-gate 4610Sstevel@tonic-gate /* putdev -d device [attr [...]] */ 4620Sstevel@tonic-gate 4630Sstevel@tonic-gate /* Check usage */ 4640Sstevel@tonic-gate if (nattrs < 0) { 4650Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, E_USAGE); 4660Sstevel@tonic-gate exitcd = EX_ERROR; 4670Sstevel@tonic-gate } else { 4680Sstevel@tonic-gate 4690Sstevel@tonic-gate /* 4700Sstevel@tonic-gate * Determine case (removing a device or attributes 4710Sstevel@tonic-gate * to a device. 4720Sstevel@tonic-gate */ 4730Sstevel@tonic-gate 4740Sstevel@tonic-gate if (nattrs == 0) { 4750Sstevel@tonic-gate 4760Sstevel@tonic-gate /* putdev -d device */ 4770Sstevel@tonic-gate 4780Sstevel@tonic-gate /* Attempt to remove the specified device */ 4790Sstevel@tonic-gate if (!(_rmdevtabrec(device))) switch(errno) { 4800Sstevel@tonic-gate 4810Sstevel@tonic-gate /* 4820Sstevel@tonic-gate * ENODEV indicates that the named device is not 4830Sstevel@tonic-gate * defined in the device table. 4840Sstevel@tonic-gate */ 4850Sstevel@tonic-gate 4860Sstevel@tonic-gate case ENODEV: 4870Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODEV, device); 4880Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 4890Sstevel@tonic-gate exitcd = EX_EXISTS; 4900Sstevel@tonic-gate break; 4910Sstevel@tonic-gate 4920Sstevel@tonic-gate /* 4930Sstevel@tonic-gate * ENOENT indicates that the device table can't 4940Sstevel@tonic-gate * be found. 4950Sstevel@tonic-gate */ 4960Sstevel@tonic-gate 4970Sstevel@tonic-gate case ENOENT: 4980Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODEVTAB, _devtabpath()); 4990Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 5000Sstevel@tonic-gate exitcd = EX_DEVTAB; 5010Sstevel@tonic-gate break; 5020Sstevel@tonic-gate 5030Sstevel@tonic-gate /* 5040Sstevel@tonic-gate * EACCES indicates that there was a problem reading the 5050Sstevel@tonic-gate * old device table or creating the new table. If the 5060Sstevel@tonic-gate * old table is readable, assume that we can't create the 5070Sstevel@tonic-gate * new table. Otherwise, assume that the old table isn't 5080Sstevel@tonic-gate * accessible. 5090Sstevel@tonic-gate */ 5100Sstevel@tonic-gate 5110Sstevel@tonic-gate case EACCES: 5120Sstevel@tonic-gate p = _devtabpath(); 5130Sstevel@tonic-gate if (access(p, R_OK) == 0) 5140Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NOMKDTAB, p); 5150Sstevel@tonic-gate else 5160Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODEVTAB, p); 5170Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 5180Sstevel@tonic-gate exitcd = EX_DEVTAB; 5190Sstevel@tonic-gate break; 5200Sstevel@tonic-gate 5210Sstevel@tonic-gate /* 5220Sstevel@tonic-gate * Some strange problem... 5230Sstevel@tonic-gate */ 5240Sstevel@tonic-gate 5250Sstevel@tonic-gate default: 5260Sstevel@tonic-gate (void) sprintf(msg, E_INTERNAL, errno); 5270Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 5280Sstevel@tonic-gate exitcd = EX_ERROR; 5290Sstevel@tonic-gate 5300Sstevel@tonic-gate } /* End switch */ 5310Sstevel@tonic-gate } 5320Sstevel@tonic-gate else { 5330Sstevel@tonic-gate 5340Sstevel@tonic-gate /* putdev -d device attr [attr [...]] */ 5350Sstevel@tonic-gate 5360Sstevel@tonic-gate /* 5370Sstevel@tonic-gate * Attempt to remove the specified attributes from the 5380Sstevel@tonic-gate * specified device. 5390Sstevel@tonic-gate */ 5400Sstevel@tonic-gate if (!(_rmdevtabattrs(device, &argv[optind], &plist))) switch(errno) { 5410Sstevel@tonic-gate 5420Sstevel@tonic-gate /* 5430Sstevel@tonic-gate * EINVAL indicates that a named attribute was not 5440Sstevel@tonic-gate * defined for the specified device or "alias" was 5450Sstevel@tonic-gate * requested. If "plist" points to a list of attrs, 5460Sstevel@tonic-gate * the former is the problem. Otherwise, the latter 5470Sstevel@tonic-gate * is the problem. 5480Sstevel@tonic-gate */ 5490Sstevel@tonic-gate 5500Sstevel@tonic-gate case EINVAL: 5510Sstevel@tonic-gate if (plist) { 5520Sstevel@tonic-gate exitcd = EX_ATTRIB; 5530Sstevel@tonic-gate for (; *plist; plist++) { 5540Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NOATTR, *plist); 5550Sstevel@tonic-gate stdmsg(MM_RECOVER, lbl, MM_WARNING, msg); 5560Sstevel@tonic-gate } 5570Sstevel@tonic-gate } else { 5580Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, E_NOALIAS); 5590Sstevel@tonic-gate exitcd = EX_ERROR; 5600Sstevel@tonic-gate } 5610Sstevel@tonic-gate break; 5620Sstevel@tonic-gate 5630Sstevel@tonic-gate /* 5640Sstevel@tonic-gate * ENODEV indicates that the named device is not 5650Sstevel@tonic-gate * defined in the device table. 5660Sstevel@tonic-gate */ 5670Sstevel@tonic-gate 5680Sstevel@tonic-gate case ENODEV: 5690Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODEV, device); 5700Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 5710Sstevel@tonic-gate exitcd = EX_EXISTS; 5720Sstevel@tonic-gate break; 5730Sstevel@tonic-gate 5740Sstevel@tonic-gate /* 5750Sstevel@tonic-gate * ENOENT indicates that the device table can't 5760Sstevel@tonic-gate * be found. 5770Sstevel@tonic-gate */ 5780Sstevel@tonic-gate 5790Sstevel@tonic-gate case ENOENT: 5800Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODEVTAB, _devtabpath()); 5810Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 5820Sstevel@tonic-gate exitcd = EX_DEVTAB; 5830Sstevel@tonic-gate break; 5840Sstevel@tonic-gate 5850Sstevel@tonic-gate /* 5860Sstevel@tonic-gate * EACCES indicates that there was a problem reading the 5870Sstevel@tonic-gate * old device table or creating the new table. If the 5880Sstevel@tonic-gate * old table is readable, assume that we can't create the 5890Sstevel@tonic-gate * new table. Otherwise, assume that the old table isn't 5900Sstevel@tonic-gate * accessible. 5910Sstevel@tonic-gate */ 5920Sstevel@tonic-gate 5930Sstevel@tonic-gate case EACCES: 5940Sstevel@tonic-gate p = _devtabpath(); 5950Sstevel@tonic-gate if (access(p, R_OK) == 0) 5960Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NOMKDTAB, p); 5970Sstevel@tonic-gate else 5980Sstevel@tonic-gate (void) snprintf(msg, sizeof(msg), E_NODEVTAB, p); 5990Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 6000Sstevel@tonic-gate exitcd = EX_DEVTAB; 6010Sstevel@tonic-gate break; 6020Sstevel@tonic-gate 6030Sstevel@tonic-gate /* 6040Sstevel@tonic-gate * Some strange problem... 6050Sstevel@tonic-gate */ 6060Sstevel@tonic-gate 6070Sstevel@tonic-gate default: 6080Sstevel@tonic-gate (void) sprintf(msg, E_INTERNAL, errno); 6090Sstevel@tonic-gate stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 6100Sstevel@tonic-gate exitcd = EX_ERROR; 6110Sstevel@tonic-gate 6120Sstevel@tonic-gate } /* End switch */ 6130Sstevel@tonic-gate 6140Sstevel@tonic-gate } /* End "putdev -d device attr [...]" case */ 6150Sstevel@tonic-gate 6160Sstevel@tonic-gate } /* End passes usage-check case */ 6170Sstevel@tonic-gate 6180Sstevel@tonic-gate } /* End -d case */ 6190Sstevel@tonic-gate 6200Sstevel@tonic-gate 6210Sstevel@tonic-gate /* Done. Return exit code (determined above) */ 6220Sstevel@tonic-gate return(exitcd); 6230Sstevel@tonic-gate } /* main() */ 624