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 #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 int 171 main(int argc, char *argv[]) 172 { 173 /* Automatic data */ 174 char **plist; /* Ptr to list of nonmembers */ 175 char *lbl; /* Ptr to label for messages */ 176 char *dgroup; /* Ptr to <dgroup> on command-line */ 177 char *p; /* Temp ptr to char */ 178 int noerr; /* FLAG, TRUE if all's well */ 179 int d_seen; /* TRUE if -a seen on command-line */ 180 int optchar; /* Option extracted */ 181 int exitcd; /* Value to return at exit */ 182 int nmems; /* Number of members on the cmd */ 183 184 185 /* Generate the label for messages */ 186 lbl = mklbl(argv[0]); 187 188 /* Extract arguments - validate usage */ 189 noerr = TRUE; 190 d_seen = FALSE; 191 opterr = FALSE; 192 while ((optchar = getopt(argc, argv, "d:")) != EOF) switch (optchar) { 193 194 case 'd': 195 if (!d_seen) 196 { 197 d_seen = TRUE; 198 dgroup = optarg; 199 } 200 else noerr = FALSE; 201 break; 202 203 case '?': 204 default: 205 noerr = FALSE; 206 } 207 208 209 /* Write a usage message if we've seen a blatant error */ 210 if (!noerr || (!d_seen && ((nmems = argc - optind - 1) < 0)) || 211 (d_seen && ((nmems = argc - optind) < 0))) { 212 stdmsg(MM_NRECOV, lbl, MM_ERROR, E_USAGE); 213 exit(EX_ERROR); 214 } 215 216 217 /* Set up */ 218 exitcd = EX_OK; 219 220 221 /* -d on the command line ? */ 222 if (d_seen) { 223 224 /* 225 * Determine case (removing a device group or members 226 * of that device group. 227 */ 228 229 if (nmems == 0) { 230 231 /* putdgrp -d dgroup */ 232 233 /* Attempt to remove the specified device */ 234 if (!(_rmdgrptabrec(dgroup))) switch(errno) { 235 236 /* 237 * EINVAL indicates that the named device-group was 238 * not found in the device-group table. 239 */ 240 241 case EINVAL: 242 (void) snprintf(msg, sizeof(msg), E_NODGRP, dgroup); 243 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 244 exitcd = EX_NODGRP; 245 break; 246 247 /* 248 * ENOENT indicates that the device-group table can't 249 * be found. 250 */ 251 252 case ENOENT: 253 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath()); 254 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 255 exitcd = EX_DGROUP; 256 break; 257 258 /* 259 * EACCES indicates that there was a problem reading the 260 * old device-group table or creating the new table. If the 261 * old table is readable, assume that we can't create the 262 * new table. Otherwise, assume that the old table isn't 263 * accessible. 264 */ 265 266 case EACCES: 267 p = _dgrptabpath(); 268 if (access(p, R_OK) == 0) 269 (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p); 270 else 271 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p); 272 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 273 exitcd = EX_DGROUP; 274 break; 275 276 /* 277 * Some strange problem... 278 */ 279 280 default: 281 (void) snprintf(msg, sizeof(msg), E_INTERNAL, errno); 282 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 283 exitcd = EX_ERROR; 284 285 } /* End switch */ 286 } 287 else { 288 289 /* putdgrp -d dgroup device [device [...]] */ 290 291 /* 292 * Attempt to remove the specified devices from the 293 * specified device-group. 294 */ 295 if (!(_rmdgrpmems(dgroup, &argv[optind], &plist))) switch(errno) { 296 297 /* 298 * ENODEV indicates that a named device was not part 299 * of the specified device group. 300 */ 301 302 case ENODEV: 303 exitcd = EX_NOMEM; 304 for (; *plist; plist++) { 305 (void) snprintf(msg, sizeof(msg), E_NOTAMEM, *plist); 306 stdmsg(MM_RECOVER, lbl, MM_WARNING, msg); 307 } 308 break; 309 310 /* 311 * EINVAL indicates that the named device-group is not 312 * defined in the device-group table. 313 */ 314 315 case EINVAL: 316 (void) snprintf(msg, sizeof(msg), E_NODGRP, dgroup); 317 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 318 exitcd = EX_NODGRP; 319 break; 320 321 /* 322 * ENOENT indicates that the device table can't 323 * be found. 324 */ 325 326 case ENOENT: 327 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath()); 328 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 329 exitcd = EX_DGROUP; 330 break; 331 332 /* 333 * EACCES indicates that there was a problem reading the 334 * old device table or creating the new table. If the 335 * old table is readable, assume that we can't create the 336 * new table. Otherwise, assume that the old table isn't 337 * accessible. 338 */ 339 340 case EACCES: 341 p = _dgrptabpath(); 342 if (access(p, R_OK) == 0) 343 (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p); 344 else 345 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p); 346 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 347 exitcd = EX_DGROUP; 348 break; 349 350 /* 351 * Some strange problem... 352 */ 353 354 default: 355 (void) sprintf(msg, E_INTERNAL, errno); 356 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 357 exitcd = EX_ERROR; 358 359 } /* End switch */ 360 361 } /* End "putdgrp -d device attr [...]" case */ 362 363 364 } /* End -d case */ 365 366 else { 367 /* Standard case (no -d on the command) */ 368 if (!(_adddgrptabrec(argv[optind], &argv[optind+1]))) switch(errno) { 369 370 /* 371 * ENOENT indicates that the device-group table does not exist. 372 */ 373 374 case ENOENT: 375 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, _dgrptabpath()); 376 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 377 exitcd = EX_DGROUP; 378 break; 379 380 /* 381 * EACCES indicates that the device-group table could not be 382 * opened or the new device-group table could not be created. 383 */ 384 385 case EACCES: 386 p = _dgrptabpath(); 387 if (access(p, R_OK) == 0) 388 (void) snprintf(msg, sizeof(msg), E_NOMKTAB, p); 389 else 390 (void) snprintf(msg, sizeof(msg), E_NODGRPTAB, p); 391 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 392 exitcd = EX_DGROUP; 393 break; 394 395 /* 396 * Some strange error (memory?) 397 */ 398 399 default: 400 (void) sprintf(msg, E_INTERNAL, errno); 401 stdmsg(MM_NRECOV, lbl, MM_ERROR, msg); 402 exitcd = EX_ERROR; 403 } 404 } 405 406 /* Done. Return exit code (determined above) */ 407 return(exitcd); 408 } /* main() */ 409