1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Implements the "putdgrp" command. 32 */ 33 #include <sys/types.h> 34 #include <stdio.h> 35 #include <stdlib.h> 36 #include <string.h> 37 #include <errno.h> 38 #include <unistd.h> 39 #include <fmtmsg.h> 40 #include <devmgmt.h> 41 #include <devtab.h> 42 43 44 /* 45 * General Purpose Constants 46 * TRUE Boolean TRUE (if not already defined) 47 * FALSE Boolean FALSE (if not already defined) 48 */ 49 50 #ifndef TRUE 51 #define TRUE (1) 52 #endif 53 54 #ifndef FALSE 55 #define FALSE (0) 56 #endif 57 58 /* 59 * Exit codes 60 * EX_OK All went well 61 * EX_ERROR Usage or internal error 62 * EX_DGROUP Had trouble accessing/reading/writing the 63 * device-group table 64 * EX_NODGRP The specified device-group does not exist 65 * EX_NOMEM One or more device-group members requested for 66 * removal was not defined for the device 67 */ 68 69 #define EX_OK 0 70 #define EX_ERROR 1 71 #define EX_DGROUP 2 72 #define EX_NODGRP 3 73 #define EX_NOMEM 4 74 75 76 /* 77 * Error messages 78 */ 79 80 #define E_USAGE "usage: putdgrp [-d] dgroup [device [...]]" 81 #define E_NODGRP "Device-group does not exist in table: %s" 82 #define E_NOTAMEM "Device-group member not found: %s" 83 #define E_NODGRPTAB "Cannot open the device-group table: %s" 84 #define E_NOMKTAB "Cannot create a new device-group table: %s" 85 #define E_INTERNAL "Internal error, errno=%d" 86 87 88 /* 89 * Macros 90 * stdmsg(r,l,s,t) Using fmtmsg(), write a standard message to the 91 * standard error stream. 92 * Where: 93 * r The recoverability of the error 94 * l The label-component 95 * s The severity-component 96 * t The text-component 97 */ 98 99 #define stdmsg(r,l,s,t) (void) fmtmsg(MM_PRINT|MM_UTIL|r,l,s,t,MM_NULLACT,MM_NULLTAG) 100 101 102 /* 103 * Static data 104 * msg Space for message's text-component 105 */ 106 107 static char msg[256]; /* Space for text of message */ 108 109 /* 110 * char *mklbl(cmd) 111 * char *cmd 112 * 113 * This function builds a standard label from the command used to invoke 114 * this process and the standard label prefix ("UX:") 115 * 116 * Arguments: 117 * char *cmd The command used to invoke this process. 118 * 119 * Returns: char * 120 * Pointer to malloc()ed space containing the standard label, 121 * or (char *) NULL if an error occurred. 122 */ 123 124 static char * 125 mklbl(cmd) 126 char *cmd; 127 { 128 /* Automatic data */ 129 char *rtn; /* Value to return */ 130 char *p; /* Temporary */ 131 132 /* Find the 1st char of the basename of the command */ 133 if (p = strrchr(cmd, '/')) p++; 134 else p = cmd; 135 136 /* Allocate and build the string value to return */ 137 if (rtn = (char *) malloc(strlen("UX:")+strlen(p)+1)) { 138 (void) strcpy(rtn, "UX:"); 139 (void) strcat(rtn, p); 140 } 141 142 /* Now that we've done all of this work, set up the environemnt 143 * so that only the text-component is written (some requirements 144 * say that standard messages are to be non-standard in SVR4.0, 145 * this is supposed to change in SVR4.1) 146 */ 147 148 (void) putenv("MSGVERB=text"); 149 150 /* Done */ 151 return(rtn); 152 } 153 154 /* 155 * putdgrp [-d] dgroup [device [...]] 156 * 157 * Options: 158 * -d 159 * 160 * Arguments: 161 * dgroup 162 * device 163 * 164 * Exit values: 165 */ 166 167 int 168 main(int argc, char *argv[]) 169 { 170 /* Automatic data */ 171 char **plist; /* Ptr to list of nonmembers */ 172 char *lbl; /* Ptr to label for messages */ 173 char *dgroup; /* Ptr to <dgroup> on command-line */ 174 char *p; /* Temp ptr to char */ 175 int noerr; /* FLAG, TRUE if all's well */ 176 int d_seen; /* TRUE if -a seen on command-line */ 177 int optchar; /* Option extracted */ 178 int exitcd; /* Value to return at exit */ 179 int nmems; /* Number of members on the cmd */ 180 181 182 /* Generate the label for messages */ 183 lbl = mklbl(argv[0]); 184 185 /* Extract arguments - validate usage */ 186 noerr = TRUE; 187 d_seen = FALSE; 188 opterr = FALSE; 189 while ((optchar = getopt(argc, argv, "d:")) != EOF) switch (optchar) { 190 191 case 'd': 192 if (!d_seen) 193 { 194 d_seen = TRUE; 195 dgroup = optarg; 196 } 197 else noerr = FALSE; 198 break; 199 200 case '?': 201 default: 202 noerr = FALSE; 203 } 204 205 206 /* Write a usage message if we've seen a blatant error */ 207 if (!noerr || (!d_seen && ((nmems = argc - optind - 1) < 0)) || 208 (d_seen && ((nmems = argc - optind) < 0))) { 209 stdmsg(MM_NRECOV, lbl, MM_ERROR, E_USAGE); 210 exit(EX_ERROR); 211 } 212 213 214 /* Set up */ 215 exitcd = EX_OK; 216 217 218 /* -d on the command line ? */ 219 if (d_seen) { 220 221 /* 222 * Determine case (removing a device group or members 223 * of that device group. 224 */ 225 226 if (nmems == 0) { 227 228 /* putdgrp -d dgroup */ 229 230 /* Attempt to remove the specified device */ 231 if (!(_rmdgrptabrec(dgroup))) switch(errno) { 232 233 /* 234 * EINVAL indicates that the named device-group was 235 * not found in the device-group table. 236 */ 237 238 case EINVAL: 239 (void) snprintf(msg, sizeof(msg), E_NODGRP, dgroup); 240 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 241 exitcd = EX_NODGRP; 242 break; 243 244 /* 245 * ENOENT indicates that the device-group table can't 246 * be found. 247 */ 248 249 case ENOENT: 250 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath()); 251 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 252 exitcd = EX_DGROUP; 253 break; 254 255 /* 256 * EACCES indicates that there was a problem reading the 257 * old device-group table or creating the new table. If the 258 * old table is readable, assume that we can't create the 259 * new table. Otherwise, assume that the old table isn't 260 * accessible. 261 */ 262 263 case EACCES: 264 p = _dgrptabpath(); 265 if (access(p, R_OK) == 0) 266 (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p); 267 else 268 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p); 269 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 270 exitcd = EX_DGROUP; 271 break; 272 273 /* 274 * Some strange problem... 275 */ 276 277 default: 278 (void) snprintf(msg, sizeof(msg), E_INTERNAL, errno); 279 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 280 exitcd = EX_ERROR; 281 282 } /* End switch */ 283 } 284 else { 285 286 /* putdgrp -d dgroup device [device [...]] */ 287 288 /* 289 * Attempt to remove the specified devices from the 290 * specified device-group. 291 */ 292 if (!(_rmdgrpmems(dgroup, &argv[optind], &plist))) switch(errno) { 293 294 /* 295 * ENODEV indicates that a named device was not part 296 * of the specified device group. 297 */ 298 299 case ENODEV: 300 exitcd = EX_NOMEM; 301 for (; *plist; plist++) { 302 (void) snprintf(msg, sizeof(msg), E_NOTAMEM, *plist); 303 stdmsg(MM_RECOVER, lbl, MM_WARNING, msg); 304 } 305 break; 306 307 /* 308 * EINVAL indicates that the named device-group is not 309 * defined in the device-group table. 310 */ 311 312 case EINVAL: 313 (void) snprintf(msg, sizeof(msg), E_NODGRP, dgroup); 314 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 315 exitcd = EX_NODGRP; 316 break; 317 318 /* 319 * ENOENT indicates that the device table can't 320 * be found. 321 */ 322 323 case ENOENT: 324 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath()); 325 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 326 exitcd = EX_DGROUP; 327 break; 328 329 /* 330 * EACCES indicates that there was a problem reading the 331 * old device table or creating the new table. If the 332 * old table is readable, assume that we can't create the 333 * new table. Otherwise, assume that the old table isn't 334 * accessible. 335 */ 336 337 case EACCES: 338 p = _dgrptabpath(); 339 if (access(p, R_OK) == 0) 340 (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p); 341 else 342 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p); 343 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 344 exitcd = EX_DGROUP; 345 break; 346 347 /* 348 * Some strange problem... 349 */ 350 351 default: 352 (void) sprintf(msg, E_INTERNAL, errno); 353 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 354 exitcd = EX_ERROR; 355 356 } /* End switch */ 357 358 } /* End "putdgrp -d device attr [...]" case */ 359 360 361 } /* End -d case */ 362 363 else { 364 /* Standard case (no -d on the command) */ 365 if (!(_adddgrptabrec(argv[optind], &argv[optind+1]))) switch(errno) { 366 367 /* 368 * ENOENT indicates that the device-group table does not exist. 369 */ 370 371 case ENOENT: 372 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath()); 373 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 374 exitcd = EX_DGROUP; 375 break; 376 377 /* 378 * EACCES indicates that the device-group table could not be 379 * opened or the new device-group table could not be created. 380 */ 381 382 case EACCES: 383 p = _dgrptabpath(); 384 if (access(p, R_OK) == 0) 385 (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p); 386 else 387 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p); 388 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 389 exitcd = EX_DGROUP; 390 break; 391 392 /* 393 * Some strange error (memory?) 394 */ 395 396 default: 397 (void) sprintf(msg, E_INTERNAL, errno); 398 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 399 exitcd = EX_ERROR; 400 } 401 } 402 403 /* Done. Return exit code (determined above) */ 404 return(exitcd); 405 } /* main() */ 406