1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 1992-2002 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <errno.h> 30*7c478bd9Sstevel@tonic-gate #include <locale.h> 31*7c478bd9Sstevel@tonic-gate #include <pwd.h> 32*7c478bd9Sstevel@tonic-gate #include <unistd.h> 33*7c478bd9Sstevel@tonic-gate #include <stdio.h> 34*7c478bd9Sstevel@tonic-gate #include <stdlib.h> 35*7c478bd9Sstevel@tonic-gate #include <string.h> 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 38*7c478bd9Sstevel@tonic-gate 39*7c478bd9Sstevel@tonic-gate #include "allocate.h" 40*7c478bd9Sstevel@tonic-gate 41*7c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 42*7c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SUNW_OST_OSCMD" 43*7c478bd9Sstevel@tonic-gate #endif 44*7c478bd9Sstevel@tonic-gate 45*7c478bd9Sstevel@tonic-gate extern void audit_allocate_argv(int, int, char *[]); 46*7c478bd9Sstevel@tonic-gate extern int audit_allocate_record(int); 47*7c478bd9Sstevel@tonic-gate 48*7c478bd9Sstevel@tonic-gate static void 49*7c478bd9Sstevel@tonic-gate usage(int func) 50*7c478bd9Sstevel@tonic-gate { 51*7c478bd9Sstevel@tonic-gate char *use[5]; 52*7c478bd9Sstevel@tonic-gate 53*7c478bd9Sstevel@tonic-gate use[0] = gettext("allocate [-s] [-U uname] [-F] device"); 54*7c478bd9Sstevel@tonic-gate use[1] = gettext("allocate [-s] [-U uname] -g dev_type"); 55*7c478bd9Sstevel@tonic-gate use[2] = gettext("deallocate [-s] [-F] device"); 56*7c478bd9Sstevel@tonic-gate use[3] = gettext("deallocate [-s] [-I]"); 57*7c478bd9Sstevel@tonic-gate use[4] = gettext("list_devices [-s] [-U uname] {-l|-n|-u} [device]"); 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate switch (func) { 60*7c478bd9Sstevel@tonic-gate case 0: 61*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n%s\n", use[0], use[1]); 62*7c478bd9Sstevel@tonic-gate break; 63*7c478bd9Sstevel@tonic-gate case 1: 64*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n%s\n", use[2], use[3]); 65*7c478bd9Sstevel@tonic-gate break; 66*7c478bd9Sstevel@tonic-gate case 2: 67*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n", use[4]); 68*7c478bd9Sstevel@tonic-gate break; 69*7c478bd9Sstevel@tonic-gate default: 70*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 71*7c478bd9Sstevel@tonic-gate use[0], use[1], use[2], use[3], use[4]); 72*7c478bd9Sstevel@tonic-gate } 73*7c478bd9Sstevel@tonic-gate } 74*7c478bd9Sstevel@tonic-gate 75*7c478bd9Sstevel@tonic-gate static void 76*7c478bd9Sstevel@tonic-gate print_error(int error, char *name) 77*7c478bd9Sstevel@tonic-gate { 78*7c478bd9Sstevel@tonic-gate char *msg; 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate switch (error) { 81*7c478bd9Sstevel@tonic-gate case SYSERROR: 82*7c478bd9Sstevel@tonic-gate msg = gettext("Unknown System error."); 83*7c478bd9Sstevel@tonic-gate break; 84*7c478bd9Sstevel@tonic-gate case IMPORT_ERR: 85*7c478bd9Sstevel@tonic-gate msg = gettext( 86*7c478bd9Sstevel@tonic-gate "User lacks authorization required for this operation."); 87*7c478bd9Sstevel@tonic-gate break; 88*7c478bd9Sstevel@tonic-gate case NODAENT: 89*7c478bd9Sstevel@tonic-gate msg = gettext( 90*7c478bd9Sstevel@tonic-gate "No device allocate file entry for specified device."); 91*7c478bd9Sstevel@tonic-gate break; 92*7c478bd9Sstevel@tonic-gate case NODMAPENT: 93*7c478bd9Sstevel@tonic-gate msg = gettext( 94*7c478bd9Sstevel@tonic-gate "No device maps file entry for specified device."); 95*7c478bd9Sstevel@tonic-gate break; 96*7c478bd9Sstevel@tonic-gate case DACLCK: 97*7c478bd9Sstevel@tonic-gate msg = gettext("Concurrent operations for specified device, " 98*7c478bd9Sstevel@tonic-gate "try later."); 99*7c478bd9Sstevel@tonic-gate break; 100*7c478bd9Sstevel@tonic-gate case DACACC: 101*7c478bd9Sstevel@tonic-gate msg = gettext( 102*7c478bd9Sstevel@tonic-gate "Can't access DAC file for the device specified."); 103*7c478bd9Sstevel@tonic-gate break; 104*7c478bd9Sstevel@tonic-gate case DEVLST: 105*7c478bd9Sstevel@tonic-gate msg = gettext( 106*7c478bd9Sstevel@tonic-gate "Could not use device list for the device specified."); 107*7c478bd9Sstevel@tonic-gate break; 108*7c478bd9Sstevel@tonic-gate case NALLOCU: 109*7c478bd9Sstevel@tonic-gate msg = gettext("Specified device is allocated to another user."); 110*7c478bd9Sstevel@tonic-gate break; 111*7c478bd9Sstevel@tonic-gate case NOTAUTH: 112*7c478bd9Sstevel@tonic-gate msg = gettext("Not authorized for specified operation."); 113*7c478bd9Sstevel@tonic-gate break; 114*7c478bd9Sstevel@tonic-gate case CNTFRC: 115*7c478bd9Sstevel@tonic-gate msg = gettext("Can't force deallocate specified device."); 116*7c478bd9Sstevel@tonic-gate break; 117*7c478bd9Sstevel@tonic-gate case CNTDEXEC: 118*7c478bd9Sstevel@tonic-gate msg = gettext( 119*7c478bd9Sstevel@tonic-gate "Can't exec device-clean program for specified device."); 120*7c478bd9Sstevel@tonic-gate break; 121*7c478bd9Sstevel@tonic-gate case NO_DEVICE: 122*7c478bd9Sstevel@tonic-gate msg = gettext( 123*7c478bd9Sstevel@tonic-gate "Can't find a device of type requested to allocate."); 124*7c478bd9Sstevel@tonic-gate break; 125*7c478bd9Sstevel@tonic-gate case DSPMISS: 126*7c478bd9Sstevel@tonic-gate msg = gettext( 127*7c478bd9Sstevel@tonic-gate "Device special file(s) missing for specified device."); 128*7c478bd9Sstevel@tonic-gate break; 129*7c478bd9Sstevel@tonic-gate case ALLOCERR: 130*7c478bd9Sstevel@tonic-gate msg = gettext("Device specified is in allocate error state."); 131*7c478bd9Sstevel@tonic-gate break; 132*7c478bd9Sstevel@tonic-gate case CHOWN_PERR: 133*7c478bd9Sstevel@tonic-gate msg = gettext("Process lacks privilege required to chown()."); 134*7c478bd9Sstevel@tonic-gate break; 135*7c478bd9Sstevel@tonic-gate case ALLOC: 136*7c478bd9Sstevel@tonic-gate msg = gettext("Device already allocated."); 137*7c478bd9Sstevel@tonic-gate break; 138*7c478bd9Sstevel@tonic-gate case ALLOC_OTHER: 139*7c478bd9Sstevel@tonic-gate msg = gettext("Device allocated to another user."); 140*7c478bd9Sstevel@tonic-gate break; 141*7c478bd9Sstevel@tonic-gate case NALLOC: 142*7c478bd9Sstevel@tonic-gate msg = gettext("Device not allocated."); 143*7c478bd9Sstevel@tonic-gate break; 144*7c478bd9Sstevel@tonic-gate case AUTHERR: 145*7c478bd9Sstevel@tonic-gate msg = gettext("Device not allocatable."); 146*7c478bd9Sstevel@tonic-gate break; 147*7c478bd9Sstevel@tonic-gate case CLEAN_ERR: 148*7c478bd9Sstevel@tonic-gate msg = gettext("Unable to clean up the device."); 149*7c478bd9Sstevel@tonic-gate break; 150*7c478bd9Sstevel@tonic-gate case SETACL_PERR: 151*7c478bd9Sstevel@tonic-gate msg = gettext("Process lacks privilege required to set ACL."); 152*7c478bd9Sstevel@tonic-gate break; 153*7c478bd9Sstevel@tonic-gate case DEVNAME_ERR: 154*7c478bd9Sstevel@tonic-gate msg = gettext("Error forming device name."); 155*7c478bd9Sstevel@tonic-gate break; 156*7c478bd9Sstevel@tonic-gate case DEVNAME_TOOLONG: 157*7c478bd9Sstevel@tonic-gate msg = gettext("Device name is too long."); 158*7c478bd9Sstevel@tonic-gate break; 159*7c478bd9Sstevel@tonic-gate default: 160*7c478bd9Sstevel@tonic-gate msg = gettext("Unknown error code."); 161*7c478bd9Sstevel@tonic-gate break; 162*7c478bd9Sstevel@tonic-gate } 163*7c478bd9Sstevel@tonic-gate 164*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", name, msg); 165*7c478bd9Sstevel@tonic-gate (void) fflush(stderr); 166*7c478bd9Sstevel@tonic-gate } 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate char *newenv[] = {"PATH=/usr/bin:/usr/sbin", 169*7c478bd9Sstevel@tonic-gate NULL, /* for LC_ALL */ 170*7c478bd9Sstevel@tonic-gate NULL, /* for LC_COLLATE */ 171*7c478bd9Sstevel@tonic-gate NULL, /* for LC_CTYPE */ 172*7c478bd9Sstevel@tonic-gate NULL, /* for LC_MESSAGES */ 173*7c478bd9Sstevel@tonic-gate NULL, /* for LC_NUMERIC */ 174*7c478bd9Sstevel@tonic-gate NULL, /* for LC_TIME */ 175*7c478bd9Sstevel@tonic-gate NULL, /* for LANG */ 176*7c478bd9Sstevel@tonic-gate NULL 177*7c478bd9Sstevel@tonic-gate }; 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate static char * 180*7c478bd9Sstevel@tonic-gate getenvent(char *name, char *env[]) 181*7c478bd9Sstevel@tonic-gate { 182*7c478bd9Sstevel@tonic-gate for (; *env != NULL; env++) { 183*7c478bd9Sstevel@tonic-gate if (strncmp(*env, name, strlen(name)) == 0) 184*7c478bd9Sstevel@tonic-gate return (*env); 185*7c478bd9Sstevel@tonic-gate } 186*7c478bd9Sstevel@tonic-gate return (NULL); 187*7c478bd9Sstevel@tonic-gate } 188*7c478bd9Sstevel@tonic-gate 189*7c478bd9Sstevel@tonic-gate int 190*7c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char *envp[]) 191*7c478bd9Sstevel@tonic-gate { 192*7c478bd9Sstevel@tonic-gate char *name, *env; 193*7c478bd9Sstevel@tonic-gate int func = -1, optflg = 0, errflg = 0, error = 0, c; 194*7c478bd9Sstevel@tonic-gate uid_t uid = getuid(); 195*7c478bd9Sstevel@tonic-gate char *uname = NULL, *device = NULL; 196*7c478bd9Sstevel@tonic-gate struct passwd *pw_ent; 197*7c478bd9Sstevel@tonic-gate int env_num = 1; /* PATH= is 0 entry */ 198*7c478bd9Sstevel@tonic-gate 199*7c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 200*7c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 201*7c478bd9Sstevel@tonic-gate 202*7c478bd9Sstevel@tonic-gate /* 203*7c478bd9Sstevel@tonic-gate * get all enviroment variables 204*7c478bd9Sstevel@tonic-gate * which affect on internationalization. 205*7c478bd9Sstevel@tonic-gate */ 206*7c478bd9Sstevel@tonic-gate env = getenvent("LC_ALL=", envp); 207*7c478bd9Sstevel@tonic-gate if (env != NULL) 208*7c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 209*7c478bd9Sstevel@tonic-gate env = getenvent("LC_COLLATE=", envp); 210*7c478bd9Sstevel@tonic-gate if (env != NULL) 211*7c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 212*7c478bd9Sstevel@tonic-gate env = getenvent("LC_CTYPE=", envp); 213*7c478bd9Sstevel@tonic-gate if (env != NULL) 214*7c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 215*7c478bd9Sstevel@tonic-gate env = getenvent("LC_MESSAGES=", envp); 216*7c478bd9Sstevel@tonic-gate if (env != NULL) 217*7c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 218*7c478bd9Sstevel@tonic-gate env = getenvent("LC_NUMERIC=", envp); 219*7c478bd9Sstevel@tonic-gate if (env != NULL) 220*7c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 221*7c478bd9Sstevel@tonic-gate env = getenvent("LC_TIME=", envp); 222*7c478bd9Sstevel@tonic-gate if (env != NULL) 223*7c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 224*7c478bd9Sstevel@tonic-gate env = getenvent("LANG=", envp); 225*7c478bd9Sstevel@tonic-gate if (env != NULL) 226*7c478bd9Sstevel@tonic-gate newenv[env_num] = env; 227*7c478bd9Sstevel@tonic-gate 228*7c478bd9Sstevel@tonic-gate if ((name = strrchr(argv[0], '/')) == NULL) 229*7c478bd9Sstevel@tonic-gate name = argv[0]; 230*7c478bd9Sstevel@tonic-gate else 231*7c478bd9Sstevel@tonic-gate name++; 232*7c478bd9Sstevel@tonic-gate 233*7c478bd9Sstevel@tonic-gate if (strcmp(name, "allocate") == 0) 234*7c478bd9Sstevel@tonic-gate func = 0; 235*7c478bd9Sstevel@tonic-gate else if (strcmp(name, "deallocate") == 0) 236*7c478bd9Sstevel@tonic-gate func = 1; 237*7c478bd9Sstevel@tonic-gate else if (strcmp(name, "list_devices") == 0) 238*7c478bd9Sstevel@tonic-gate func = 2; 239*7c478bd9Sstevel@tonic-gate else { 240*7c478bd9Sstevel@tonic-gate usage(ALL); 241*7c478bd9Sstevel@tonic-gate exit(1); 242*7c478bd9Sstevel@tonic-gate } 243*7c478bd9Sstevel@tonic-gate 244*7c478bd9Sstevel@tonic-gate audit_allocate_argv(func, argc, argv); 245*7c478bd9Sstevel@tonic-gate 246*7c478bd9Sstevel@tonic-gate while ((c = getopt(argc, argv, "slnugIU:F")) != -1) 247*7c478bd9Sstevel@tonic-gate switch (c) { 248*7c478bd9Sstevel@tonic-gate case 's': 249*7c478bd9Sstevel@tonic-gate optflg |= SILENT; 250*7c478bd9Sstevel@tonic-gate break; 251*7c478bd9Sstevel@tonic-gate case 'U': 252*7c478bd9Sstevel@tonic-gate optflg |= USERID; 253*7c478bd9Sstevel@tonic-gate uname = optarg; 254*7c478bd9Sstevel@tonic-gate break; 255*7c478bd9Sstevel@tonic-gate case 'g': 256*7c478bd9Sstevel@tonic-gate optflg |= TYPE; 257*7c478bd9Sstevel@tonic-gate break; 258*7c478bd9Sstevel@tonic-gate case 'l': 259*7c478bd9Sstevel@tonic-gate optflg |= LIST; 260*7c478bd9Sstevel@tonic-gate break; 261*7c478bd9Sstevel@tonic-gate case 'n': 262*7c478bd9Sstevel@tonic-gate optflg |= FREE; 263*7c478bd9Sstevel@tonic-gate break; 264*7c478bd9Sstevel@tonic-gate case 'u': 265*7c478bd9Sstevel@tonic-gate optflg |= CURRENT; 266*7c478bd9Sstevel@tonic-gate break; 267*7c478bd9Sstevel@tonic-gate case 'F': 268*7c478bd9Sstevel@tonic-gate optflg |= FORCE; 269*7c478bd9Sstevel@tonic-gate break; 270*7c478bd9Sstevel@tonic-gate case 'I': 271*7c478bd9Sstevel@tonic-gate optflg |= FORCE_ALL; 272*7c478bd9Sstevel@tonic-gate break; 273*7c478bd9Sstevel@tonic-gate case '?': 274*7c478bd9Sstevel@tonic-gate errflg++; 275*7c478bd9Sstevel@tonic-gate break; 276*7c478bd9Sstevel@tonic-gate default : 277*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext("Bad option '%c'\n"), c); 278*7c478bd9Sstevel@tonic-gate } 279*7c478bd9Sstevel@tonic-gate 280*7c478bd9Sstevel@tonic-gate if (optind < argc) { 281*7c478bd9Sstevel@tonic-gate device = argv[optind]; 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate if (device == NULL && !(optflg & (LIST | FREE | CURRENT | FORCE_ALL))) 285*7c478bd9Sstevel@tonic-gate errflg++; 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate if (errflg) { 288*7c478bd9Sstevel@tonic-gate usage(func); 289*7c478bd9Sstevel@tonic-gate exit(2); 290*7c478bd9Sstevel@tonic-gate } 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate if (optflg & USERID) { 293*7c478bd9Sstevel@tonic-gate if ((pw_ent = getpwnam(uname)) == NULL) { 294*7c478bd9Sstevel@tonic-gate (void) fprintf(stderr, gettext( 295*7c478bd9Sstevel@tonic-gate "Invalid user name -- %s -- \n"), uname); 296*7c478bd9Sstevel@tonic-gate exit(4); 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate uid = pw_ent->pw_uid; 299*7c478bd9Sstevel@tonic-gate } 300*7c478bd9Sstevel@tonic-gate 301*7c478bd9Sstevel@tonic-gate if (func == 0) { 302*7c478bd9Sstevel@tonic-gate if (optflg & ~ALLOC_OPTS) { 303*7c478bd9Sstevel@tonic-gate usage(func); 304*7c478bd9Sstevel@tonic-gate exit(3); 305*7c478bd9Sstevel@tonic-gate } else { 306*7c478bd9Sstevel@tonic-gate error = allocate(optflg, uid, device); 307*7c478bd9Sstevel@tonic-gate } 308*7c478bd9Sstevel@tonic-gate } else if (func == 1) { 309*7c478bd9Sstevel@tonic-gate if (optflg & ~DEALLOC_OPTS) { 310*7c478bd9Sstevel@tonic-gate usage(func); 311*7c478bd9Sstevel@tonic-gate exit(3); 312*7c478bd9Sstevel@tonic-gate } else { 313*7c478bd9Sstevel@tonic-gate error = deallocate(optflg, uid, device); 314*7c478bd9Sstevel@tonic-gate } 315*7c478bd9Sstevel@tonic-gate } else if (func == 2) { 316*7c478bd9Sstevel@tonic-gate if (optflg & ~LIST_OPTS) { 317*7c478bd9Sstevel@tonic-gate usage(func); 318*7c478bd9Sstevel@tonic-gate exit(3); 319*7c478bd9Sstevel@tonic-gate } else { 320*7c478bd9Sstevel@tonic-gate error = list_devices(optflg, uid, device); 321*7c478bd9Sstevel@tonic-gate } 322*7c478bd9Sstevel@tonic-gate } 323*7c478bd9Sstevel@tonic-gate (void) audit_allocate_record(error); 324*7c478bd9Sstevel@tonic-gate 325*7c478bd9Sstevel@tonic-gate if (error) { 326*7c478bd9Sstevel@tonic-gate if (!(optflg & SILENT)) 327*7c478bd9Sstevel@tonic-gate print_error(error, name); 328*7c478bd9Sstevel@tonic-gate exit(error); 329*7c478bd9Sstevel@tonic-gate } 330*7c478bd9Sstevel@tonic-gate 331*7c478bd9Sstevel@tonic-gate return (0); 332*7c478bd9Sstevel@tonic-gate } 333