xref: /titanic_52/usr/src/cmd/allocate/allocate.c (revision 10ddde3aee60d88fa580028fcf7642a87e80a2c6)
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