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