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 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <errno.h> 30 #include <locale.h> 31 #include <pwd.h> 32 #include <unistd.h> 33 #include <stdio.h> 34 #include <stdlib.h> 35 #include <string.h> 36 37 #include <sys/types.h> 38 39 #include "allocate.h" 40 41 #if !defined(TEXT_DOMAIN) 42 #define TEXT_DOMAIN "SUNW_OST_OSCMD" 43 #endif 44 45 extern void audit_allocate_argv(int, int, char *[]); 46 extern int audit_allocate_record(int); 47 48 static void 49 usage(int func) 50 { 51 char *use[7]; 52 53 use[0] = gettext("allocate [-s] [-U uname] [-F] device"); 54 use[1] = gettext("allocate [-s] [-U uname] -g dev_type"); 55 use[2] = gettext("deallocate [-s] [-F] device"); 56 use[3] = gettext("deallocate [-s] -I"); 57 use[4] = gettext("list_devices [-s] [-U uid] -l [device]"); 58 use[5] = gettext("list_devices [-s] [-U uid] -n [device]"); 59 use[6] = gettext("list_devices [-s] [-U uid] -u [device]"); 60 61 switch (func) { 62 case 0: 63 (void) fprintf(stderr, "%s\n%s\n", use[0], use[1]); 64 break; 65 case 1: 66 (void) fprintf(stderr, "%s\n%s\n", use[2], use[3]); 67 break; 68 case 2: 69 (void) fprintf(stderr, "%s\n%s\n%s\n", use[4], use[5], 70 use[6]); 71 break; 72 default: 73 (void) fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 74 use[0], use[1], use[2], use[3], use[4]); 75 } 76 exit(1); 77 } 78 79 static void 80 print_error(int error, char *name) 81 { 82 char *msg; 83 84 switch (error) { 85 case SYSERROR: 86 msg = gettext("Unknown System error."); 87 break; 88 case IMPORT_ERR: 89 msg = gettext( 90 "User lacks authorization required for this operation."); 91 break; 92 case NODAENT: 93 msg = gettext( 94 "No device allocate file entry for specified device."); 95 break; 96 case NODMAPENT: 97 msg = gettext( 98 "No device maps file entry for specified device."); 99 break; 100 case DACLCK: 101 msg = gettext("Concurrent operations for specified device, " 102 "try later."); 103 break; 104 case DACACC: 105 msg = gettext( 106 "Can't access DAC file for the device specified."); 107 break; 108 case DEVLST: 109 msg = gettext( 110 "Could not use device list for the device specified."); 111 break; 112 case NALLOCU: 113 msg = gettext("Specified device is allocated to another user."); 114 break; 115 case NOTAUTH: 116 msg = gettext("Not authorized for specified operation."); 117 break; 118 case CNTFRC: 119 msg = gettext("Can't force deallocate specified device."); 120 break; 121 case CNTDEXEC: 122 msg = gettext( 123 "Can't exec device-clean program for specified device."); 124 break; 125 case NO_DEVICE: 126 msg = gettext( 127 "Can't find a device of type requested to allocate."); 128 break; 129 case DSPMISS: 130 msg = gettext( 131 "Device special file(s) missing for specified device."); 132 break; 133 case ALLOCERR: 134 msg = gettext("Device specified is in allocate error state."); 135 break; 136 case CHOWN_PERR: 137 msg = gettext("Process lacks privilege required to chown()."); 138 break; 139 case ALLOC: 140 msg = gettext("Device already allocated."); 141 break; 142 case ALLOC_OTHER: 143 msg = gettext("Device allocated to another user."); 144 break; 145 case NALLOC: 146 msg = gettext("Device not allocated."); 147 break; 148 case AUTHERR: 149 msg = gettext("Device not allocatable."); 150 break; 151 case CLEAN_ERR: 152 msg = gettext("Unable to clean up the device."); 153 break; 154 case SETACL_PERR: 155 msg = gettext("Process lacks privilege required to set ACL."); 156 break; 157 case DEVNAME_ERR: 158 msg = gettext("Error forming device name."); 159 break; 160 case DEVNAME_TOOLONG: 161 msg = gettext("Device name is too long."); 162 break; 163 default: 164 msg = gettext("Unknown error code."); 165 break; 166 } 167 168 (void) fprintf(stderr, "%s: %s\n", name, msg); 169 (void) fflush(stderr); 170 } 171 172 char *newenv[] = {"PATH=/usr/bin:/usr/sbin", 173 NULL, /* for LC_ALL */ 174 NULL, /* for LC_COLLATE */ 175 NULL, /* for LC_CTYPE */ 176 NULL, /* for LC_MESSAGES */ 177 NULL, /* for LC_NUMERIC */ 178 NULL, /* for LC_TIME */ 179 NULL, /* for LANG */ 180 NULL 181 }; 182 183 static char * 184 getenvent(char *name, char *env[]) 185 { 186 for (; *env != NULL; env++) { 187 if (strncmp(*env, name, strlen(name)) == 0) 188 return (*env); 189 } 190 return (NULL); 191 } 192 193 int 194 main(int argc, char *argv[], char *envp[]) 195 { 196 char *name, *env; 197 int func = -1, optflg = 0, error = 0, c; 198 uid_t uid = getuid(); 199 char *uname = NULL, *device = NULL; 200 struct passwd *pw_ent; 201 int env_num = 1; /* PATH= is 0 entry */ 202 203 (void) setlocale(LC_ALL, ""); 204 (void) textdomain(TEXT_DOMAIN); 205 206 /* 207 * get all enviroment variables 208 * which affect on internationalization. 209 */ 210 env = getenvent("LC_ALL=", envp); 211 if (env != NULL) 212 newenv[env_num++] = env; 213 env = getenvent("LC_COLLATE=", envp); 214 if (env != NULL) 215 newenv[env_num++] = env; 216 env = getenvent("LC_CTYPE=", envp); 217 if (env != NULL) 218 newenv[env_num++] = env; 219 env = getenvent("LC_MESSAGES=", envp); 220 if (env != NULL) 221 newenv[env_num++] = env; 222 env = getenvent("LC_NUMERIC=", envp); 223 if (env != NULL) 224 newenv[env_num++] = env; 225 env = getenvent("LC_TIME=", envp); 226 if (env != NULL) 227 newenv[env_num++] = env; 228 env = getenvent("LANG=", envp); 229 if (env != NULL) 230 newenv[env_num] = env; 231 232 if ((name = strrchr(argv[0], '/')) == NULL) 233 name = argv[0]; 234 else 235 name++; 236 237 if (strcmp(name, "allocate") == 0) 238 func = 0; 239 else if (strcmp(name, "deallocate") == 0) 240 func = 1; 241 else if (strcmp(name, "list_devices") == 0) 242 func = 2; 243 else { 244 usage(ALL); 245 } 246 247 audit_allocate_argv(func, argc, argv); 248 249 if (func == 0) { /* allocate */ 250 while ((c = getopt(argc, argv, "sU:Fg")) != -1) { 251 switch (c) { 252 case 's': 253 optflg |= SILENT; 254 break; 255 case 'U': 256 optflg |= USERNAME; 257 uname = optarg; 258 break; 259 case 'g': 260 optflg |= TYPE; 261 break; 262 case 'F': 263 optflg |= FORCE; 264 break; 265 case '?': 266 default : 267 usage(func); 268 } 269 } 270 271 if ((optflg & TYPE) && (optflg & FORCE)) 272 usage(func); 273 274 /* 275 * allocate(1) must be supplied with one device argument 276 */ 277 if ((argc - optind) != 1) { 278 usage(func); 279 } else { 280 device = argv[optind]; 281 } 282 } 283 284 else if (func == 1) { /* deallocate */ 285 while ((c = getopt(argc, argv, "sFI")) != -1) { 286 switch (c) { 287 case 's': 288 optflg |= SILENT; 289 break; 290 case 'F': 291 optflg |= FORCE; 292 break; 293 case 'I': 294 optflg |= FORCE_ALL; 295 break; 296 case '?': 297 default : 298 usage(func); 299 } 300 } 301 302 if ((optflg & FORCE) && (optflg & FORCE_ALL)) 303 usage(func); 304 305 /* 306 * deallocate(1) must be supplied with one device 307 * argument unless the '-I' argument is supplied 308 */ 309 if (!(optflg & FORCE_ALL)) { 310 if ((argc - optind) != 1) { 311 usage(func); 312 } else { 313 device = argv[optind]; 314 } 315 } else { 316 if ((argc - optind) >= 1) { 317 usage(func); 318 } 319 } 320 } 321 322 else if (func == 2) { /* list_devices */ 323 while ((c = getopt(argc, argv, "sU:lnu")) != -1) { 324 switch (c) { 325 case 's': 326 optflg |= SILENT; 327 break; 328 case 'U': 329 optflg |= USERID; 330 uid = atoi(optarg); 331 break; 332 case 'l': 333 optflg |= LIST; 334 break; 335 case 'n': 336 optflg |= FREE; 337 break; 338 case 'u': 339 optflg |= CURRENT; 340 break; 341 case '?': 342 default : 343 usage(func); 344 } 345 } 346 347 if (((optflg & LIST) && (optflg & FREE)) || 348 ((optflg & LIST) && (optflg & CURRENT)) || 349 ((optflg & FREE) && (optflg & CURRENT)) || 350 (!(optflg & (LIST | FREE | CURRENT)))) 351 usage(func); 352 353 /* 354 * list_devices(1) takes an optional device argument 355 */ 356 if ((argc - optind) == 1) { 357 device = argv[optind]; 358 } else { 359 if ((argc - optind) > 1) { 360 usage(func); 361 } 362 } 363 } 364 365 if (optflg & USERNAME) { 366 if ((pw_ent = getpwnam(uname)) == NULL) { 367 (void) fprintf(stderr, gettext( 368 "Invalid user name -- %s -- \n"), uname); 369 exit(1); 370 } 371 uid = pw_ent->pw_uid; 372 } 373 374 if (optflg & USERID) { 375 if ((pw_ent = getpwuid(uid)) == NULL) { 376 (void) fprintf(stderr, gettext( 377 "Invalid user ID -- %d -- \n"), uid); 378 exit(1); 379 } 380 uid = pw_ent->pw_uid; 381 } 382 383 if (func == 0) { 384 error = allocate(optflg, uid, device); 385 } else if (func == 1) { 386 error = deallocate(optflg, uid, device); 387 } else if (func == 2) { 388 error = list_devices(optflg, uid, device); 389 } 390 391 (void) audit_allocate_record(error); 392 393 if (error) { 394 if (!(optflg & SILENT)) 395 print_error(error, name); 396 exit(error); 397 } 398 399 return (0); 400 } 401