17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 545916cd2Sjpk * Common Development and Distribution License (the "License"). 645916cd2Sjpk * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 2145916cd2Sjpk 227c478bd9Sstevel@tonic-gate /* 23*10ddde3aSaj * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 287c478bd9Sstevel@tonic-gate 297c478bd9Sstevel@tonic-gate #include <errno.h> 307c478bd9Sstevel@tonic-gate #include <locale.h> 317c478bd9Sstevel@tonic-gate #include <pwd.h> 327c478bd9Sstevel@tonic-gate #include <unistd.h> 337c478bd9Sstevel@tonic-gate #include <stdio.h> 347c478bd9Sstevel@tonic-gate #include <stdlib.h> 357c478bd9Sstevel@tonic-gate #include <string.h> 3645916cd2Sjpk #include <ctype.h> 37facf4a8dSllai1 #include <fcntl.h> 3845916cd2Sjpk #include <nss_dbdefs.h> 397c478bd9Sstevel@tonic-gate #include <sys/types.h> 40facf4a8dSllai1 #include <sys/stat.h> 4145916cd2Sjpk #include <sys/wait.h> 4245916cd2Sjpk #include <tsol/label.h> 4345916cd2Sjpk #include <zone.h> 4445916cd2Sjpk #include <bsm/devalloc.h> 457c478bd9Sstevel@tonic-gate #include "allocate.h" 467c478bd9Sstevel@tonic-gate 477c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN) 487c478bd9Sstevel@tonic-gate #define TEXT_DOMAIN "SUNW_OST_OSCMD" 497c478bd9Sstevel@tonic-gate #endif 507c478bd9Sstevel@tonic-gate 5145916cd2Sjpk #define ALLOC "allocate" 5245916cd2Sjpk #define DEALLOC "deallocate" 5345916cd2Sjpk #define LIST "list_devices" 5445916cd2Sjpk 557c478bd9Sstevel@tonic-gate extern void audit_allocate_argv(int, int, char *[]); 567c478bd9Sstevel@tonic-gate extern int audit_allocate_record(int); 577c478bd9Sstevel@tonic-gate 5845916cd2Sjpk int system_labeled = 0; 5945916cd2Sjpk static int windowing = 0; 6045916cd2Sjpk static int wdwmsg(char *name, char *msg); 6145916cd2Sjpk 627c478bd9Sstevel@tonic-gate static void 637c478bd9Sstevel@tonic-gate usage(int func) 647c478bd9Sstevel@tonic-gate { 6545916cd2Sjpk if (system_labeled) { 66*10ddde3aSaj char *use[6]; 6745916cd2Sjpk 6845916cd2Sjpk use[0] = gettext("allocate [-s] [-w] [-U uname] [-z zonename] " 69*10ddde3aSaj "[-F] device|-g dev-type"); 70*10ddde3aSaj use[1] = gettext("deallocate [-s] [-w] [-z zonename] " 71*10ddde3aSaj "[-F] device|-c dev-class|-g dev-type"); 72*10ddde3aSaj use[2] = gettext("deallocate [-s] [-w] [-z zonename] -I"); 73*10ddde3aSaj use[3] = gettext("list_devices [-s] [-U uid] [-z zonename] " 74*10ddde3aSaj "[-a [-w]] -l|-n|-u [device]"); 75*10ddde3aSaj use[4] = gettext("list_devices [-s] [-U uid] [-z zonename] " 76*10ddde3aSaj "[-a [-w]] [-l|-n|-u] -c dev-class"); 77*10ddde3aSaj use[5] = gettext("list_devices [-s] -d [dev-type]"); 7845916cd2Sjpk 7945916cd2Sjpk switch (func) { 8045916cd2Sjpk case 0: 81*10ddde3aSaj (void) fprintf(stderr, "%s\n", use[0]); 8245916cd2Sjpk break; 8345916cd2Sjpk case 1: 84*10ddde3aSaj (void) fprintf(stderr, "%s\n%s\n", 85*10ddde3aSaj use[1], use[2]); 8645916cd2Sjpk break; 8745916cd2Sjpk case 2: 88*10ddde3aSaj (void) fprintf(stderr, "%s\n%s\n%s\n", 89*10ddde3aSaj use[3], use[4], use[5]); 9045916cd2Sjpk break; 9145916cd2Sjpk default: 9245916cd2Sjpk (void) fprintf(stderr, 93*10ddde3aSaj "%s\n%s\n%s\n%s\n%s\n%s\n", 9445916cd2Sjpk use[0], use[1], use[2], use[3], use[4], 95*10ddde3aSaj use[5]); 9645916cd2Sjpk } 9745916cd2Sjpk } else { 98*10ddde3aSaj char *use[5]; 997c478bd9Sstevel@tonic-gate 100*10ddde3aSaj use[0] = gettext("allocate " 101*10ddde3aSaj "[-s] [-U uname] [-F] device|-g dev-type"); 102*10ddde3aSaj use[1] = gettext("deallocate [-s] [-F] device|-c dev-class"); 103*10ddde3aSaj use[2] = gettext("deallocate [-s] -I"); 104*10ddde3aSaj use[3] = gettext("list_devices " 105*10ddde3aSaj "[-s] [-U uid] -l|-n|-u [device]"); 106*10ddde3aSaj use[4] = gettext("list_devices " 107*10ddde3aSaj "[-s] [-U uid] [-l|-n|-u] -c dev-class"); 1087c478bd9Sstevel@tonic-gate 1097c478bd9Sstevel@tonic-gate switch (func) { 1107c478bd9Sstevel@tonic-gate case 0: 111*10ddde3aSaj (void) fprintf(stderr, "%s\n", use[0]); 1127c478bd9Sstevel@tonic-gate break; 1137c478bd9Sstevel@tonic-gate case 1: 11445916cd2Sjpk (void) fprintf(stderr, "%s\n%s\n", 115*10ddde3aSaj use[1], use[2]); 1167c478bd9Sstevel@tonic-gate break; 1177c478bd9Sstevel@tonic-gate case 2: 118*10ddde3aSaj (void) fprintf(stderr, "%s\n%s\n", 119*10ddde3aSaj use[3], use[4]); 1207c478bd9Sstevel@tonic-gate break; 1217c478bd9Sstevel@tonic-gate default: 122*10ddde3aSaj (void) fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 123*10ddde3aSaj use[0], use[1], use[2], use[3], use[4]); 12445916cd2Sjpk } 1257c478bd9Sstevel@tonic-gate } 12640e2b7c9Spaulson exit(1); 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 12945916cd2Sjpk void 1307c478bd9Sstevel@tonic-gate print_error(int error, char *name) 1317c478bd9Sstevel@tonic-gate { 1327c478bd9Sstevel@tonic-gate char *msg; 13345916cd2Sjpk char msgbuf[200]; 1347c478bd9Sstevel@tonic-gate 1357c478bd9Sstevel@tonic-gate switch (error) { 13645916cd2Sjpk case ALLOCUERR: 1377c478bd9Sstevel@tonic-gate msg = gettext("Specified device is allocated to another user."); 1387c478bd9Sstevel@tonic-gate break; 13945916cd2Sjpk case CHOWNERR: 14045916cd2Sjpk msg = gettext("Failed to chown."); 1417c478bd9Sstevel@tonic-gate break; 14245916cd2Sjpk case CLEANERR: 14345916cd2Sjpk msg = gettext("Unable to clean up device."); 1447c478bd9Sstevel@tonic-gate break; 14545916cd2Sjpk case CNTDEXECERR: 1467c478bd9Sstevel@tonic-gate msg = gettext( 1477c478bd9Sstevel@tonic-gate "Can't exec device-clean program for specified device."); 1487c478bd9Sstevel@tonic-gate break; 14945916cd2Sjpk case CNTFRCERR: 15045916cd2Sjpk msg = gettext("Can't force deallocate specified device."); 1517c478bd9Sstevel@tonic-gate break; 15245916cd2Sjpk case DACACCERR: 15345916cd2Sjpk msg = gettext( 15445916cd2Sjpk "Can't access DAC file for the device specified."); 15545916cd2Sjpk break; 15645916cd2Sjpk case DAOFFERR: 15745916cd2Sjpk msg = gettext( 15845916cd2Sjpk "Device allocation feature is not activated " 15945916cd2Sjpk "on this system."); 16045916cd2Sjpk break; 16145916cd2Sjpk case DAUTHERR: 16245916cd2Sjpk msg = gettext("Device not allocatable."); 16345916cd2Sjpk break; 16445916cd2Sjpk case DEFATTRSERR: 16545916cd2Sjpk msg = gettext("No default attributes for specified " 16645916cd2Sjpk "device type."); 16745916cd2Sjpk break; 16845916cd2Sjpk case DEVLKERR: 16945916cd2Sjpk msg = gettext("Concurrent operations for specified device, " 17045916cd2Sjpk "try later."); 17145916cd2Sjpk break; 17245916cd2Sjpk case DEVLONGERR: 17345916cd2Sjpk msg = gettext("Device name is too long."); 17445916cd2Sjpk break; 17545916cd2Sjpk case DEVNALLOCERR: 17645916cd2Sjpk msg = gettext("Device not allocated."); 17745916cd2Sjpk break; 17845916cd2Sjpk case DEVNAMEERR: 17945916cd2Sjpk msg = gettext("Device name error."); 18045916cd2Sjpk break; 18145916cd2Sjpk case DEVSTATEERR: 18245916cd2Sjpk msg = gettext("Device specified is in allocate error state."); 18345916cd2Sjpk break; 18445916cd2Sjpk case DEVZONEERR: 18545916cd2Sjpk msg = gettext("Can't find name of the zone to which " 18645916cd2Sjpk "device is allocated."); 18745916cd2Sjpk break; 18845916cd2Sjpk case DSPMISSERR: 1897c478bd9Sstevel@tonic-gate msg = gettext( 1907c478bd9Sstevel@tonic-gate "Device special file(s) missing for specified device."); 1917c478bd9Sstevel@tonic-gate break; 19245916cd2Sjpk case LABELRNGERR: 19345916cd2Sjpk msg = gettext( 19445916cd2Sjpk "Operation inconsistent with device's label range."); 1957c478bd9Sstevel@tonic-gate break; 19645916cd2Sjpk case LOGINDEVPERMERR: 19745916cd2Sjpk msg = gettext("Device controlled by logindevperm(4)"); 1987c478bd9Sstevel@tonic-gate break; 19945916cd2Sjpk case NODAERR: 20045916cd2Sjpk msg = gettext("No entry for specified device."); 20145916cd2Sjpk break; 20245916cd2Sjpk case NODMAPERR: 20345916cd2Sjpk msg = gettext("No entry for specified device."); 20445916cd2Sjpk break; 20545916cd2Sjpk case PREALLOCERR: 2067c478bd9Sstevel@tonic-gate msg = gettext("Device already allocated."); 2077c478bd9Sstevel@tonic-gate break; 20845916cd2Sjpk case SETACLERR: 20945916cd2Sjpk msg = gettext("Failed to set ACL."); 2107c478bd9Sstevel@tonic-gate break; 21145916cd2Sjpk case UAUTHERR: 21245916cd2Sjpk msg = gettext( 21345916cd2Sjpk "User lacks authorization required for this operation."); 2147c478bd9Sstevel@tonic-gate break; 21545916cd2Sjpk case ZONEERR: 21645916cd2Sjpk msg = gettext("Failed to configure device in zone."); 2177c478bd9Sstevel@tonic-gate break; 2187c478bd9Sstevel@tonic-gate default: 2197c478bd9Sstevel@tonic-gate msg = gettext("Unknown error code."); 2207c478bd9Sstevel@tonic-gate break; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 22345916cd2Sjpk if (windowing) { 22445916cd2Sjpk (void) snprintf(msgbuf, sizeof (msgbuf), "%s: %s\n", name, msg); 22545916cd2Sjpk (void) wdwmsg(name, msgbuf); 22645916cd2Sjpk } else { 2277c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s\n", name, msg); 2287c478bd9Sstevel@tonic-gate (void) fflush(stderr); 2297c478bd9Sstevel@tonic-gate } 23045916cd2Sjpk } 2317c478bd9Sstevel@tonic-gate 2327c478bd9Sstevel@tonic-gate char *newenv[] = {"PATH=/usr/bin:/usr/sbin", 2337c478bd9Sstevel@tonic-gate NULL, /* for LC_ALL */ 2347c478bd9Sstevel@tonic-gate NULL, /* for LC_COLLATE */ 2357c478bd9Sstevel@tonic-gate NULL, /* for LC_CTYPE */ 2367c478bd9Sstevel@tonic-gate NULL, /* for LC_MESSAGES */ 2377c478bd9Sstevel@tonic-gate NULL, /* for LC_NUMERIC */ 2387c478bd9Sstevel@tonic-gate NULL, /* for LC_TIME */ 2397c478bd9Sstevel@tonic-gate NULL, /* for LANG */ 2407c478bd9Sstevel@tonic-gate NULL 2417c478bd9Sstevel@tonic-gate }; 2427c478bd9Sstevel@tonic-gate 2437c478bd9Sstevel@tonic-gate static char * 2447c478bd9Sstevel@tonic-gate getenvent(char *name, char *env[]) 2457c478bd9Sstevel@tonic-gate { 2467c478bd9Sstevel@tonic-gate for (; *env != NULL; env++) { 2477c478bd9Sstevel@tonic-gate if (strncmp(*env, name, strlen(name)) == 0) 2487c478bd9Sstevel@tonic-gate return (*env); 2497c478bd9Sstevel@tonic-gate } 2507c478bd9Sstevel@tonic-gate return (NULL); 2517c478bd9Sstevel@tonic-gate } 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate int 2547c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char *envp[]) 2557c478bd9Sstevel@tonic-gate { 2567c478bd9Sstevel@tonic-gate char *name, *env; 25740e2b7c9Spaulson int func = -1, optflg = 0, error = 0, c; 25845916cd2Sjpk zoneid_t zoneid; 25945916cd2Sjpk uid_t uid; 26045916cd2Sjpk char *uname = NULL, *device = NULL, *zonename = NULL; 26145916cd2Sjpk char *zname; 26245916cd2Sjpk char pw_buf[NSS_BUFLEN_PASSWD]; 26345916cd2Sjpk struct passwd pw_ent; 2647c478bd9Sstevel@tonic-gate int env_num = 1; /* PATH= is 0 entry */ 265facf4a8dSllai1 #ifdef DEBUG 266facf4a8dSllai1 struct stat statbuf; 267facf4a8dSllai1 #endif 2687c478bd9Sstevel@tonic-gate 2697c478bd9Sstevel@tonic-gate (void) setlocale(LC_ALL, ""); 2707c478bd9Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN); 2717c478bd9Sstevel@tonic-gate 27245916cd2Sjpk system_labeled = is_system_labeled(); 27345916cd2Sjpk 274facf4a8dSllai1 /* test hook: see also mkdevalloc.c and devfsadm.c */ 275facf4a8dSllai1 if (!system_labeled) { 276facf4a8dSllai1 system_labeled = is_system_labeled_debug(&statbuf); 277facf4a8dSllai1 if (system_labeled) { 278facf4a8dSllai1 fprintf(stderr, "/ALLOCATE_FORCE_LABEL is set,\n" 279facf4a8dSllai1 "forcing system label on for testing...\n"); 280facf4a8dSllai1 } 281facf4a8dSllai1 } 282facf4a8dSllai1 2837c478bd9Sstevel@tonic-gate /* 2847c478bd9Sstevel@tonic-gate * get all enviroment variables 2857c478bd9Sstevel@tonic-gate * which affect on internationalization. 2867c478bd9Sstevel@tonic-gate */ 2877c478bd9Sstevel@tonic-gate env = getenvent("LC_ALL=", envp); 2887c478bd9Sstevel@tonic-gate if (env != NULL) 2897c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 2907c478bd9Sstevel@tonic-gate env = getenvent("LC_COLLATE=", envp); 2917c478bd9Sstevel@tonic-gate if (env != NULL) 2927c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 2937c478bd9Sstevel@tonic-gate env = getenvent("LC_CTYPE=", envp); 2947c478bd9Sstevel@tonic-gate if (env != NULL) 2957c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 2967c478bd9Sstevel@tonic-gate env = getenvent("LC_MESSAGES=", envp); 2977c478bd9Sstevel@tonic-gate if (env != NULL) 2987c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 2997c478bd9Sstevel@tonic-gate env = getenvent("LC_NUMERIC=", envp); 3007c478bd9Sstevel@tonic-gate if (env != NULL) 3017c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 3027c478bd9Sstevel@tonic-gate env = getenvent("LC_TIME=", envp); 3037c478bd9Sstevel@tonic-gate if (env != NULL) 3047c478bd9Sstevel@tonic-gate newenv[env_num++] = env; 3057c478bd9Sstevel@tonic-gate env = getenvent("LANG=", envp); 3067c478bd9Sstevel@tonic-gate if (env != NULL) 3077c478bd9Sstevel@tonic-gate newenv[env_num] = env; 3087c478bd9Sstevel@tonic-gate 3097c478bd9Sstevel@tonic-gate if ((name = strrchr(argv[0], '/')) == NULL) 3107c478bd9Sstevel@tonic-gate name = argv[0]; 3117c478bd9Sstevel@tonic-gate else 3127c478bd9Sstevel@tonic-gate name++; 3137c478bd9Sstevel@tonic-gate 31445916cd2Sjpk if (strcmp(name, ALLOC) == 0) 3157c478bd9Sstevel@tonic-gate func = 0; 31645916cd2Sjpk else if (strcmp(name, DEALLOC) == 0) 3177c478bd9Sstevel@tonic-gate func = 1; 31845916cd2Sjpk else if (strcmp(name, LIST) == 0) 3197c478bd9Sstevel@tonic-gate func = 2; 32045916cd2Sjpk else 32145916cd2Sjpk usage(-1); 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate audit_allocate_argv(func, argc, argv); 3247c478bd9Sstevel@tonic-gate 32545916cd2Sjpk if (system_labeled) { 32645916cd2Sjpk /* 32745916cd2Sjpk * allocate, deallocate, list_devices run in 32845916cd2Sjpk * global zone only. 32945916cd2Sjpk */ 33045916cd2Sjpk zoneid = getzoneid(); 33145916cd2Sjpk if (zoneid != GLOBAL_ZONEID) 33245916cd2Sjpk exit(GLOBALERR); 33345916cd2Sjpk zname = GLOBAL_ZONENAME; 33445916cd2Sjpk /* 33545916cd2Sjpk * check if device allocation is activated. 33645916cd2Sjpk */ 33745916cd2Sjpk if (da_is_on() == 0) { 33845916cd2Sjpk (void) fprintf(stderr, "%s%s", 33945916cd2Sjpk gettext("Turn device allocation on"), 34045916cd2Sjpk gettext(" to use this feature.\n")); 34145916cd2Sjpk exit(DAOFFERR); 34245916cd2Sjpk } 34345916cd2Sjpk } 34445916cd2Sjpk 34540e2b7c9Spaulson if (func == 0) { /* allocate */ 346*10ddde3aSaj while ((c = getopt(argc, argv, "g:swz:FU:")) != -1) { 34740e2b7c9Spaulson switch (c) { 34845916cd2Sjpk case 'g': 34945916cd2Sjpk optflg |= TYPE; 350*10ddde3aSaj device = optarg; 35145916cd2Sjpk break; 35240e2b7c9Spaulson case 's': 35340e2b7c9Spaulson optflg |= SILENT; 35440e2b7c9Spaulson break; 35545916cd2Sjpk case 'w': 35645916cd2Sjpk if (system_labeled) { 35745916cd2Sjpk optflg |= WINDOWING; 35845916cd2Sjpk windowing = 1; 35945916cd2Sjpk } else { 36045916cd2Sjpk usage(func); 36145916cd2Sjpk } 36245916cd2Sjpk break; 36345916cd2Sjpk case 'z': 36445916cd2Sjpk if (system_labeled) { 36545916cd2Sjpk optflg |= ZONENAME; 36645916cd2Sjpk zonename = optarg; 36745916cd2Sjpk } else { 36845916cd2Sjpk usage(func); 36945916cd2Sjpk } 37045916cd2Sjpk break; 37145916cd2Sjpk case 'F': 37245916cd2Sjpk optflg |= FORCE; 37345916cd2Sjpk break; 37440e2b7c9Spaulson case 'U': 37540e2b7c9Spaulson optflg |= USERNAME; 37640e2b7c9Spaulson uname = optarg; 37740e2b7c9Spaulson break; 37840e2b7c9Spaulson case '?': 37940e2b7c9Spaulson default : 38040e2b7c9Spaulson usage(func); 38140e2b7c9Spaulson } 38240e2b7c9Spaulson } 38340e2b7c9Spaulson 38440e2b7c9Spaulson /* 38540e2b7c9Spaulson * allocate(1) must be supplied with one device argument 38640e2b7c9Spaulson */ 387*10ddde3aSaj if (device && ((argc - optind) >= 1)) 38840e2b7c9Spaulson usage(func); 389*10ddde3aSaj if (device == NULL) { 390*10ddde3aSaj if ((argc - optind) != 1) 391*10ddde3aSaj usage(func); 39240e2b7c9Spaulson device = argv[optind]; 39340e2b7c9Spaulson } 39440e2b7c9Spaulson } 39540e2b7c9Spaulson 39640e2b7c9Spaulson else if (func == 1) { /* deallocate */ 397*10ddde3aSaj while ((c = getopt(argc, argv, "c:g:swz:FI")) != -1) { 39840e2b7c9Spaulson switch (c) { 399*10ddde3aSaj case 'c': 400*10ddde3aSaj if (optflg & (TYPE | FORCE_ALL)) 40145916cd2Sjpk usage(func); 402*10ddde3aSaj optflg |= CLASS; 403*10ddde3aSaj device = optarg; 404*10ddde3aSaj break; 405*10ddde3aSaj case 'g': 406*10ddde3aSaj if (system_labeled) { 407*10ddde3aSaj if (optflg & (CLASS | FORCE_ALL)) 408*10ddde3aSaj usage(func); 409*10ddde3aSaj optflg |= TYPE; 410*10ddde3aSaj device = optarg; 411*10ddde3aSaj } else { 412*10ddde3aSaj usage(func); 413*10ddde3aSaj } 41445916cd2Sjpk break; 41540e2b7c9Spaulson case 's': 41640e2b7c9Spaulson optflg |= SILENT; 41740e2b7c9Spaulson break; 41845916cd2Sjpk case 'w': 41945916cd2Sjpk if (system_labeled) { 42045916cd2Sjpk optflg |= WINDOWING; 42145916cd2Sjpk windowing = 1; 42245916cd2Sjpk } else { 42345916cd2Sjpk usage(func); 42445916cd2Sjpk } 42545916cd2Sjpk break; 42645916cd2Sjpk case 'z': 42745916cd2Sjpk if (system_labeled) { 42845916cd2Sjpk optflg |= ZONENAME; 42945916cd2Sjpk zonename = optarg; 43045916cd2Sjpk } else { 43145916cd2Sjpk usage(func); 43245916cd2Sjpk } 43345916cd2Sjpk break; 43440e2b7c9Spaulson case 'F': 435*10ddde3aSaj if (optflg & FORCE_ALL) 436*10ddde3aSaj usage(func); 43740e2b7c9Spaulson optflg |= FORCE; 43840e2b7c9Spaulson break; 43940e2b7c9Spaulson case 'I': 440*10ddde3aSaj if (optflg & (CLASS | TYPE | FORCE)) 441*10ddde3aSaj usage(func); 44240e2b7c9Spaulson optflg |= FORCE_ALL; 44340e2b7c9Spaulson break; 44440e2b7c9Spaulson case '?': 44540e2b7c9Spaulson default : 44640e2b7c9Spaulson usage(func); 44740e2b7c9Spaulson } 44840e2b7c9Spaulson } 44940e2b7c9Spaulson 45040e2b7c9Spaulson /* 45140e2b7c9Spaulson * deallocate(1) must be supplied with one device 45240e2b7c9Spaulson * argument unless the '-I' argument is supplied 45340e2b7c9Spaulson */ 454*10ddde3aSaj if (device || (optflg & FORCE_ALL)) { 455*10ddde3aSaj if ((argc - optind) >= 1) 45640e2b7c9Spaulson usage(func); 457*10ddde3aSaj } else if (device == NULL) { 458*10ddde3aSaj if ((argc - optind) != 1) 459*10ddde3aSaj usage(func); 46040e2b7c9Spaulson device = argv[optind]; 46140e2b7c9Spaulson } 46240e2b7c9Spaulson } 46340e2b7c9Spaulson 46440e2b7c9Spaulson else if (func == 2) { /* list_devices */ 465*10ddde3aSaj while ((c = getopt(argc, argv, "ac:dlnsuwz:U:")) != -1) { 4667c478bd9Sstevel@tonic-gate switch (c) { 46745916cd2Sjpk case 'a': 46845916cd2Sjpk if (system_labeled) { 46945916cd2Sjpk /* 47045916cd2Sjpk * list auths, cleaning programs, 47145916cd2Sjpk * labels. 47245916cd2Sjpk */ 473*10ddde3aSaj if (optflg & LISTDEFS) 474*10ddde3aSaj usage(func); 47545916cd2Sjpk optflg |= LISTATTRS; 47645916cd2Sjpk } else { 47745916cd2Sjpk usage(func); 47845916cd2Sjpk } 47945916cd2Sjpk break; 480*10ddde3aSaj case 'c': 481*10ddde3aSaj optflg |= CLASS; 482*10ddde3aSaj device = optarg; 483*10ddde3aSaj break; 48445916cd2Sjpk case 'd': 48545916cd2Sjpk if (system_labeled) { 48645916cd2Sjpk /* 487*10ddde3aSaj * List devalloc_defaults 488*10ddde3aSaj * This cannot used with anything other 489*10ddde3aSaj * than -s. 49045916cd2Sjpk */ 491*10ddde3aSaj if (optflg & (LISTATTRS | CLASS | 492*10ddde3aSaj LISTALL | LISTFREE | LISTALLOC | 493*10ddde3aSaj WINDOWING | ZONENAME | USERID)) 494*10ddde3aSaj usage(func); 49545916cd2Sjpk optflg |= LISTDEFS; 49645916cd2Sjpk } else { 49745916cd2Sjpk usage(func); 49845916cd2Sjpk } 49945916cd2Sjpk break; 50045916cd2Sjpk case 'l': 501*10ddde3aSaj if (optflg & (LISTFREE | LISTALLOC | LISTDEFS)) 502*10ddde3aSaj usage(func); 50345916cd2Sjpk optflg |= LISTALL; 50445916cd2Sjpk break; 50545916cd2Sjpk case 'n': 506*10ddde3aSaj if (optflg & (LISTALL | LISTALLOC | LISTDEFS)) 507*10ddde3aSaj usage(func); 50845916cd2Sjpk optflg |= LISTFREE; 50945916cd2Sjpk break; 5107c478bd9Sstevel@tonic-gate case 's': 5117c478bd9Sstevel@tonic-gate optflg |= SILENT; 5127c478bd9Sstevel@tonic-gate break; 51345916cd2Sjpk case 'u': 514*10ddde3aSaj if (optflg & (LISTALL | LISTFREE | LISTDEFS)) 515*10ddde3aSaj usage(func); 51645916cd2Sjpk optflg |= LISTALLOC; 51745916cd2Sjpk break; 51845916cd2Sjpk case 'w': 51945916cd2Sjpk if (system_labeled) { 520*10ddde3aSaj if (optflg & LISTDEFS) 521*10ddde3aSaj usage(func); 52245916cd2Sjpk optflg |= WINDOWING; 52345916cd2Sjpk } else { 52445916cd2Sjpk usage(func); 52545916cd2Sjpk } 52645916cd2Sjpk break; 52745916cd2Sjpk case 'z': 52845916cd2Sjpk if (system_labeled) { 529*10ddde3aSaj if (optflg & LISTDEFS) 530*10ddde3aSaj usage(func); 53145916cd2Sjpk optflg |= ZONENAME; 53245916cd2Sjpk zonename = optarg; 53345916cd2Sjpk } else { 53445916cd2Sjpk usage(func); 53545916cd2Sjpk } 53645916cd2Sjpk break; 5377c478bd9Sstevel@tonic-gate case 'U': 538*10ddde3aSaj if (optflg & LISTDEFS) 539*10ddde3aSaj usage(func); 5407c478bd9Sstevel@tonic-gate optflg |= USERID; 54140e2b7c9Spaulson uid = atoi(optarg); 5427c478bd9Sstevel@tonic-gate break; 5437c478bd9Sstevel@tonic-gate case '?': 5447c478bd9Sstevel@tonic-gate default : 5457c478bd9Sstevel@tonic-gate usage(func); 54640e2b7c9Spaulson } 5477c478bd9Sstevel@tonic-gate } 5487c478bd9Sstevel@tonic-gate 54945916cd2Sjpk if (system_labeled) { 550*10ddde3aSaj if (!(optflg & (LISTALL | LISTFREE | LISTALLOC | 551*10ddde3aSaj LISTDEFS | WINDOWING))) { 552*10ddde3aSaj if (!(optflg & CLASS)) 55340e2b7c9Spaulson usage(func); 554*10ddde3aSaj } 555*10ddde3aSaj } else if (!(optflg & (LISTALL | LISTFREE | LISTALLOC))) { 556*10ddde3aSaj if (!(optflg & CLASS)) 55745916cd2Sjpk usage(func); 55845916cd2Sjpk } 55940e2b7c9Spaulson 56040e2b7c9Spaulson /* 561*10ddde3aSaj * list_devices(1) takes an optional device argument. 56240e2b7c9Spaulson */ 563*10ddde3aSaj if (device && ((argc - optind) >= 1)) 56440e2b7c9Spaulson usage(func); 565*10ddde3aSaj if (device == NULL) { 566*10ddde3aSaj if ((argc - optind) == 1) 567*10ddde3aSaj device = argv[optind]; 568*10ddde3aSaj else if ((argc - optind) > 1) 569*10ddde3aSaj usage(func); 57040e2b7c9Spaulson } 57140e2b7c9Spaulson } 57240e2b7c9Spaulson 57340e2b7c9Spaulson if (optflg & USERNAME) { 57445916cd2Sjpk if (getpwnam_r(uname, &pw_ent, pw_buf, sizeof (pw_buf)) == 57545916cd2Sjpk NULL) { 57645916cd2Sjpk (void) fprintf(stderr, 57745916cd2Sjpk gettext("Invalid user name -- %s -- \n"), uname); 57840e2b7c9Spaulson exit(1); 57940e2b7c9Spaulson } 58045916cd2Sjpk uid = pw_ent.pw_uid; 58145916cd2Sjpk } else if (optflg & USERID) { 58245916cd2Sjpk if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL) { 58345916cd2Sjpk (void) fprintf(stderr, 58445916cd2Sjpk gettext("Invalid user ID -- %d -- \n"), uid); 58540e2b7c9Spaulson exit(1); 5867c478bd9Sstevel@tonic-gate } 58745916cd2Sjpk uid = pw_ent.pw_uid; 58845916cd2Sjpk } else { 58945916cd2Sjpk /* 59045916cd2Sjpk * caller's uid is the default if no user specified. 59145916cd2Sjpk */ 59245916cd2Sjpk uid = getuid(); 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 59545916cd2Sjpk /* 59645916cd2Sjpk * global zone is the default if no zonename specified. 59745916cd2Sjpk */ 59845916cd2Sjpk if (zonename == NULL) { 59945916cd2Sjpk zonename = zname; 60045916cd2Sjpk } else { 60145916cd2Sjpk if (zone_get_id(zonename, &zoneid) != 0) { 60245916cd2Sjpk (void) fprintf(stderr, 60345916cd2Sjpk gettext("Invalid zone name -- %s -- \n"), zonename); 60445916cd2Sjpk exit(1); 6057c478bd9Sstevel@tonic-gate } 60645916cd2Sjpk } 60745916cd2Sjpk 60845916cd2Sjpk if (func == 0) 60945916cd2Sjpk error = allocate(optflg, uid, device, zonename); 61045916cd2Sjpk else if (func == 1) 61145916cd2Sjpk error = deallocate(optflg, uid, device, zonename); 61245916cd2Sjpk else if (func == 2) 61345916cd2Sjpk error = list_devices(optflg, uid, device, zonename); 61440e2b7c9Spaulson 6157c478bd9Sstevel@tonic-gate (void) audit_allocate_record(error); 6167c478bd9Sstevel@tonic-gate 6177c478bd9Sstevel@tonic-gate if (error) { 6187c478bd9Sstevel@tonic-gate if (!(optflg & SILENT)) 6197c478bd9Sstevel@tonic-gate print_error(error, name); 6207c478bd9Sstevel@tonic-gate exit(error); 6217c478bd9Sstevel@tonic-gate } 6227c478bd9Sstevel@tonic-gate 6237c478bd9Sstevel@tonic-gate return (0); 6247c478bd9Sstevel@tonic-gate } 62545916cd2Sjpk 62645916cd2Sjpk /* 62745916cd2Sjpk * Display error message via /etc/security/lib/wdwmsg script 62845916cd2Sjpk */ 62945916cd2Sjpk static int 63045916cd2Sjpk wdwmsg(char *name, char *msg) 63145916cd2Sjpk { 63245916cd2Sjpk pid_t child_pid; 63345916cd2Sjpk pid_t wait_pid; 63445916cd2Sjpk int child_status; 63545916cd2Sjpk 63645916cd2Sjpk /* Fork a child */ 63745916cd2Sjpk switch (child_pid = fork()) { 63845916cd2Sjpk case -1: /* FAILURE */ 63945916cd2Sjpk return (-1); 64045916cd2Sjpk break; 64145916cd2Sjpk 64245916cd2Sjpk case 0: /* CHILD */ 64345916cd2Sjpk (void) execl("/etc/security/lib/wdwmsg", "wdwmsg", msg, 64445916cd2Sjpk name, "OK", NULL); 64545916cd2Sjpk /* If exec failed, send message to stderr */ 64645916cd2Sjpk (void) fprintf(stderr, "%s", msg); 64745916cd2Sjpk return (-1); 64845916cd2Sjpk 64945916cd2Sjpk default: /* PARENT */ 65045916cd2Sjpk /* Wait for child to exit */ 65145916cd2Sjpk wait_pid = waitpid(child_pid, &child_status, 0); 65245916cd2Sjpk if ((wait_pid < 0) && (errno == ECHILD)) 65345916cd2Sjpk return (0); 65445916cd2Sjpk if ((wait_pid < 0) || (wait_pid != child_pid)) 65545916cd2Sjpk return (-1); 65645916cd2Sjpk if (WIFEXITED(child_status)) 65745916cd2Sjpk return (WEXITSTATUS(child_status)); 65845916cd2Sjpk if (WIFSIGNALED(child_status)) 65945916cd2Sjpk return (WTERMSIG(child_status)); 66045916cd2Sjpk return (0); 66145916cd2Sjpk } 66245916cd2Sjpk } 663