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 1992-2002 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[5]; 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 uname] {-l|-n|-u} [device]"); 58 59 switch (func) { 60 case 0: 61 (void) fprintf(stderr, "%s\n%s\n", use[0], use[1]); 62 break; 63 case 1: 64 (void) fprintf(stderr, "%s\n%s\n", use[2], use[3]); 65 break; 66 case 2: 67 (void) fprintf(stderr, "%s\n", use[4]); 68 break; 69 default: 70 (void) fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 71 use[0], use[1], use[2], use[3], use[4]); 72 } 73 } 74 75 static void 76 print_error(int error, char *name) 77 { 78 char *msg; 79 80 switch (error) { 81 case SYSERROR: 82 msg = gettext("Unknown System error."); 83 break; 84 case IMPORT_ERR: 85 msg = gettext( 86 "User lacks authorization required for this operation."); 87 break; 88 case NODAENT: 89 msg = gettext( 90 "No device allocate file entry for specified device."); 91 break; 92 case NODMAPENT: 93 msg = gettext( 94 "No device maps file entry for specified device."); 95 break; 96 case DACLCK: 97 msg = gettext("Concurrent operations for specified device, " 98 "try later."); 99 break; 100 case DACACC: 101 msg = gettext( 102 "Can't access DAC file for the device specified."); 103 break; 104 case DEVLST: 105 msg = gettext( 106 "Could not use device list for the device specified."); 107 break; 108 case NALLOCU: 109 msg = gettext("Specified device is allocated to another user."); 110 break; 111 case NOTAUTH: 112 msg = gettext("Not authorized for specified operation."); 113 break; 114 case CNTFRC: 115 msg = gettext("Can't force deallocate specified device."); 116 break; 117 case CNTDEXEC: 118 msg = gettext( 119 "Can't exec device-clean program for specified device."); 120 break; 121 case NO_DEVICE: 122 msg = gettext( 123 "Can't find a device of type requested to allocate."); 124 break; 125 case DSPMISS: 126 msg = gettext( 127 "Device special file(s) missing for specified device."); 128 break; 129 case ALLOCERR: 130 msg = gettext("Device specified is in allocate error state."); 131 break; 132 case CHOWN_PERR: 133 msg = gettext("Process lacks privilege required to chown()."); 134 break; 135 case ALLOC: 136 msg = gettext("Device already allocated."); 137 break; 138 case ALLOC_OTHER: 139 msg = gettext("Device allocated to another user."); 140 break; 141 case NALLOC: 142 msg = gettext("Device not allocated."); 143 break; 144 case AUTHERR: 145 msg = gettext("Device not allocatable."); 146 break; 147 case CLEAN_ERR: 148 msg = gettext("Unable to clean up the device."); 149 break; 150 case SETACL_PERR: 151 msg = gettext("Process lacks privilege required to set ACL."); 152 break; 153 case DEVNAME_ERR: 154 msg = gettext("Error forming device name."); 155 break; 156 case DEVNAME_TOOLONG: 157 msg = gettext("Device name is too long."); 158 break; 159 default: 160 msg = gettext("Unknown error code."); 161 break; 162 } 163 164 (void) fprintf(stderr, "%s: %s\n", name, msg); 165 (void) fflush(stderr); 166 } 167 168 char *newenv[] = {"PATH=/usr/bin:/usr/sbin", 169 NULL, /* for LC_ALL */ 170 NULL, /* for LC_COLLATE */ 171 NULL, /* for LC_CTYPE */ 172 NULL, /* for LC_MESSAGES */ 173 NULL, /* for LC_NUMERIC */ 174 NULL, /* for LC_TIME */ 175 NULL, /* for LANG */ 176 NULL 177 }; 178 179 static char * 180 getenvent(char *name, char *env[]) 181 { 182 for (; *env != NULL; env++) { 183 if (strncmp(*env, name, strlen(name)) == 0) 184 return (*env); 185 } 186 return (NULL); 187 } 188 189 int 190 main(int argc, char *argv[], char *envp[]) 191 { 192 char *name, *env; 193 int func = -1, optflg = 0, errflg = 0, error = 0, c; 194 uid_t uid = getuid(); 195 char *uname = NULL, *device = NULL; 196 struct passwd *pw_ent; 197 int env_num = 1; /* PATH= is 0 entry */ 198 199 (void) setlocale(LC_ALL, ""); 200 (void) textdomain(TEXT_DOMAIN); 201 202 /* 203 * get all enviroment variables 204 * which affect on internationalization. 205 */ 206 env = getenvent("LC_ALL=", envp); 207 if (env != NULL) 208 newenv[env_num++] = env; 209 env = getenvent("LC_COLLATE=", envp); 210 if (env != NULL) 211 newenv[env_num++] = env; 212 env = getenvent("LC_CTYPE=", envp); 213 if (env != NULL) 214 newenv[env_num++] = env; 215 env = getenvent("LC_MESSAGES=", envp); 216 if (env != NULL) 217 newenv[env_num++] = env; 218 env = getenvent("LC_NUMERIC=", envp); 219 if (env != NULL) 220 newenv[env_num++] = env; 221 env = getenvent("LC_TIME=", envp); 222 if (env != NULL) 223 newenv[env_num++] = env; 224 env = getenvent("LANG=", envp); 225 if (env != NULL) 226 newenv[env_num] = env; 227 228 if ((name = strrchr(argv[0], '/')) == NULL) 229 name = argv[0]; 230 else 231 name++; 232 233 if (strcmp(name, "allocate") == 0) 234 func = 0; 235 else if (strcmp(name, "deallocate") == 0) 236 func = 1; 237 else if (strcmp(name, "list_devices") == 0) 238 func = 2; 239 else { 240 usage(ALL); 241 exit(1); 242 } 243 244 audit_allocate_argv(func, argc, argv); 245 246 while ((c = getopt(argc, argv, "slnugIU:F")) != -1) 247 switch (c) { 248 case 's': 249 optflg |= SILENT; 250 break; 251 case 'U': 252 optflg |= USERID; 253 uname = optarg; 254 break; 255 case 'g': 256 optflg |= TYPE; 257 break; 258 case 'l': 259 optflg |= LIST; 260 break; 261 case 'n': 262 optflg |= FREE; 263 break; 264 case 'u': 265 optflg |= CURRENT; 266 break; 267 case 'F': 268 optflg |= FORCE; 269 break; 270 case 'I': 271 optflg |= FORCE_ALL; 272 break; 273 case '?': 274 errflg++; 275 break; 276 default : 277 (void) fprintf(stderr, gettext("Bad option '%c'\n"), c); 278 } 279 280 if (optind < argc) { 281 device = argv[optind]; 282 } 283 284 if (device == NULL && !(optflg & (LIST | FREE | CURRENT | FORCE_ALL))) 285 errflg++; 286 287 if (errflg) { 288 usage(func); 289 exit(2); 290 } 291 292 if (optflg & USERID) { 293 if ((pw_ent = getpwnam(uname)) == NULL) { 294 (void) fprintf(stderr, gettext( 295 "Invalid user name -- %s -- \n"), uname); 296 exit(4); 297 } 298 uid = pw_ent->pw_uid; 299 } 300 301 if (func == 0) { 302 if (optflg & ~ALLOC_OPTS) { 303 usage(func); 304 exit(3); 305 } else { 306 error = allocate(optflg, uid, device); 307 } 308 } else if (func == 1) { 309 if (optflg & ~DEALLOC_OPTS) { 310 usage(func); 311 exit(3); 312 } else { 313 error = deallocate(optflg, uid, device); 314 } 315 } else if (func == 2) { 316 if (optflg & ~LIST_OPTS) { 317 usage(func); 318 exit(3); 319 } else { 320 error = list_devices(optflg, uid, device); 321 } 322 } 323 (void) audit_allocate_record(error); 324 325 if (error) { 326 if (!(optflg & SILENT)) 327 print_error(error, name); 328 exit(error); 329 } 330 331 return (0); 332 } 333