xref: /titanic_50/usr/src/cmd/allocate/allocate.c (revision facf4a8d7b59fde89a8662b4f4c73a758e6c402c)
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 /*
2340e2b7c9Spaulson  * Copyright 2006 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>
37*facf4a8dSllai1 #include <fcntl.h>
3845916cd2Sjpk #include <nss_dbdefs.h>
397c478bd9Sstevel@tonic-gate #include <sys/types.h>
40*facf4a8dSllai1 #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) {
6645916cd2Sjpk 		char *use[9];
6745916cd2Sjpk 
6845916cd2Sjpk 		use[0] = gettext("allocate [-s] [-w] [-U uname] [-z zonename] "
6945916cd2Sjpk 		    "[-F] device");
7045916cd2Sjpk 		use[1] = gettext("allocate [-s] [-w] [-U uname] [-z zonename] "
7145916cd2Sjpk 		    "[-F] -g dev_type");
7245916cd2Sjpk 		use[2] = gettext("deallocate [-s] [-w] [-z zonename] "
7345916cd2Sjpk 		    "[-F] device");
7445916cd2Sjpk 		use[3] = gettext("deallocate [-s] [-w] [-z zonename] "
7545916cd2Sjpk 		    "[-F] -g dev_type");
7645916cd2Sjpk 		use[4] = gettext("deallocate [-s] [-w] [-z zonename] -I");
7745916cd2Sjpk 		use[5] = gettext("list_devices [-s] [-U uid] [-z zonename] "
7845916cd2Sjpk 		    "[-a] -l [device]");
7945916cd2Sjpk 		use[6] = gettext("list_devices [-s] [-U uid] [-z zonename] "
8045916cd2Sjpk 		    "[-a] -n [device]");
8145916cd2Sjpk 		use[7] = gettext("list_devices [-s] [-U uid] [-z zonename] "
8245916cd2Sjpk 		    "[-a] -u [device]");
8345916cd2Sjpk 		use[8] = gettext("list_devices [-s] -d dev_type");
8445916cd2Sjpk 
8545916cd2Sjpk 		switch (func) {
8645916cd2Sjpk 			case 0:
8745916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n",
8845916cd2Sjpk 				    use[0], use[1]);
8945916cd2Sjpk 				break;
9045916cd2Sjpk 			case 1:
9145916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n%s\n",
9245916cd2Sjpk 				    use[2], use[3], use[4]);
9345916cd2Sjpk 				break;
9445916cd2Sjpk 			case 2:
9545916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n%s\n%s\n",
9645916cd2Sjpk 				    use[5], use[6], use[7], use[8]);
9745916cd2Sjpk 				break;
9845916cd2Sjpk 			default:
9945916cd2Sjpk 				(void) fprintf(stderr,
10045916cd2Sjpk 				    "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
10145916cd2Sjpk 				    use[0], use[1], use[2], use[3], use[4],
10245916cd2Sjpk 				    use[5], use[6], use[7], use[8]);
10345916cd2Sjpk 		}
10445916cd2Sjpk 	} else {
10540e2b7c9Spaulson 		char *use[7];
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 		use[0] = gettext("allocate [-s] [-U uname] [-F] device");
1087c478bd9Sstevel@tonic-gate 		use[1] = gettext("allocate [-s] [-U uname] -g dev_type");
1097c478bd9Sstevel@tonic-gate 		use[2] = gettext("deallocate [-s] [-F] device");
11040e2b7c9Spaulson 		use[3] = gettext("deallocate [-s] -I");
11140e2b7c9Spaulson 		use[4] = gettext("list_devices [-s] [-U uid] -l [device]");
11240e2b7c9Spaulson 		use[5] = gettext("list_devices [-s] [-U uid] -n [device]");
11340e2b7c9Spaulson 		use[6] = gettext("list_devices [-s] [-U uid] -u [device]");
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 		switch (func) {
1167c478bd9Sstevel@tonic-gate 			case 0:
11745916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n",
11845916cd2Sjpk 				    use[0], use[1]);
1197c478bd9Sstevel@tonic-gate 				break;
1207c478bd9Sstevel@tonic-gate 			case 1:
12145916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n",
12245916cd2Sjpk 				    use[2], use[3]);
1237c478bd9Sstevel@tonic-gate 				break;
1247c478bd9Sstevel@tonic-gate 			case 2:
12545916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n%s\n",
12645916cd2Sjpk 				    use[4], use[5], use[6]);
1277c478bd9Sstevel@tonic-gate 				break;
1287c478bd9Sstevel@tonic-gate 			default:
12945916cd2Sjpk 				(void) fprintf(stderr,
13045916cd2Sjpk 				    "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
13145916cd2Sjpk 					use[0], use[1], use[2], use[3], use[4],
13245916cd2Sjpk 					use[5], use[6]);
13345916cd2Sjpk 		}
1347c478bd9Sstevel@tonic-gate 	}
13540e2b7c9Spaulson 	exit(1);
1367c478bd9Sstevel@tonic-gate }
1377c478bd9Sstevel@tonic-gate 
13845916cd2Sjpk void
1397c478bd9Sstevel@tonic-gate print_error(int error, char *name)
1407c478bd9Sstevel@tonic-gate {
1417c478bd9Sstevel@tonic-gate 	char	*msg;
14245916cd2Sjpk 	char	msgbuf[200];
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	switch (error) {
14545916cd2Sjpk 	case ALLOCUERR:
1467c478bd9Sstevel@tonic-gate 		msg = gettext("Specified device is allocated to another user.");
1477c478bd9Sstevel@tonic-gate 		break;
14845916cd2Sjpk 	case CHOWNERR:
14945916cd2Sjpk 		msg = gettext("Failed to chown.");
1507c478bd9Sstevel@tonic-gate 		break;
15145916cd2Sjpk 	case CLEANERR:
15245916cd2Sjpk 		msg = gettext("Unable to clean up device.");
1537c478bd9Sstevel@tonic-gate 		break;
15445916cd2Sjpk 	case CNTDEXECERR:
1557c478bd9Sstevel@tonic-gate 		msg = gettext(
1567c478bd9Sstevel@tonic-gate 		    "Can't exec device-clean program for specified device.");
1577c478bd9Sstevel@tonic-gate 		break;
15845916cd2Sjpk 	case CNTFRCERR:
15945916cd2Sjpk 		msg = gettext("Can't force deallocate specified device.");
1607c478bd9Sstevel@tonic-gate 		break;
16145916cd2Sjpk 	case DACACCERR:
16245916cd2Sjpk 		msg = gettext(
16345916cd2Sjpk 		    "Can't access DAC file for the device specified.");
16445916cd2Sjpk 		break;
16545916cd2Sjpk 	case DAOFFERR:
16645916cd2Sjpk 		msg = gettext(
16745916cd2Sjpk 		    "Device allocation feature is not activated "
16845916cd2Sjpk 		    "on this system.");
16945916cd2Sjpk 		break;
17045916cd2Sjpk 	case DAUTHERR:
17145916cd2Sjpk 		msg = gettext("Device not allocatable.");
17245916cd2Sjpk 		break;
17345916cd2Sjpk 	case DEFATTRSERR:
17445916cd2Sjpk 		msg = gettext("No default attributes for specified "
17545916cd2Sjpk 		    "device type.");
17645916cd2Sjpk 		break;
17745916cd2Sjpk 	case DEVLKERR:
17845916cd2Sjpk 		msg = gettext("Concurrent operations for specified device, "
17945916cd2Sjpk 		    "try later.");
18045916cd2Sjpk 		break;
18145916cd2Sjpk 	case DEVLONGERR:
18245916cd2Sjpk 		msg = gettext("Device name is too long.");
18345916cd2Sjpk 		break;
18445916cd2Sjpk 	case DEVNALLOCERR:
18545916cd2Sjpk 		msg = gettext("Device not allocated.");
18645916cd2Sjpk 		break;
18745916cd2Sjpk 	case DEVNAMEERR:
18845916cd2Sjpk 		msg = gettext("Device name error.");
18945916cd2Sjpk 		break;
19045916cd2Sjpk 	case DEVSTATEERR:
19145916cd2Sjpk 		msg = gettext("Device specified is in allocate error state.");
19245916cd2Sjpk 		break;
19345916cd2Sjpk 	case DEVZONEERR:
19445916cd2Sjpk 		msg = gettext("Can't find name of the zone to which "
19545916cd2Sjpk 		    "device is allocated.");
19645916cd2Sjpk 		break;
19745916cd2Sjpk 	case DSPMISSERR:
1987c478bd9Sstevel@tonic-gate 		msg = gettext(
1997c478bd9Sstevel@tonic-gate 		    "Device special file(s) missing for specified device.");
2007c478bd9Sstevel@tonic-gate 		break;
20145916cd2Sjpk 	case LABELRNGERR:
20245916cd2Sjpk 		msg = gettext(
20345916cd2Sjpk 		    "Operation inconsistent with device's label range.");
2047c478bd9Sstevel@tonic-gate 		break;
20545916cd2Sjpk 	case LOGINDEVPERMERR:
20645916cd2Sjpk 		msg = gettext("Device controlled by logindevperm(4)");
2077c478bd9Sstevel@tonic-gate 		break;
20845916cd2Sjpk 	case NODAERR:
20945916cd2Sjpk 		msg = gettext("No entry for specified device.");
21045916cd2Sjpk 		break;
21145916cd2Sjpk 	case NODMAPERR:
21245916cd2Sjpk 		msg = gettext("No entry for specified device.");
21345916cd2Sjpk 		break;
21445916cd2Sjpk 	case PREALLOCERR:
2157c478bd9Sstevel@tonic-gate 		msg = gettext("Device already allocated.");
2167c478bd9Sstevel@tonic-gate 		break;
21745916cd2Sjpk 	case SETACLERR:
21845916cd2Sjpk 		msg = gettext("Failed to set ACL.");
2197c478bd9Sstevel@tonic-gate 		break;
22045916cd2Sjpk 	case UAUTHERR:
22145916cd2Sjpk 		msg = gettext(
22245916cd2Sjpk 		    "User lacks authorization required for this operation.");
2237c478bd9Sstevel@tonic-gate 		break;
22445916cd2Sjpk 	case ZONEERR:
22545916cd2Sjpk 		msg = gettext("Failed to configure device in zone.");
2267c478bd9Sstevel@tonic-gate 		break;
2277c478bd9Sstevel@tonic-gate 	default:
2287c478bd9Sstevel@tonic-gate 		msg = gettext("Unknown error code.");
2297c478bd9Sstevel@tonic-gate 		break;
2307c478bd9Sstevel@tonic-gate 	}
2317c478bd9Sstevel@tonic-gate 
23245916cd2Sjpk 	if (windowing) {
23345916cd2Sjpk 		(void) snprintf(msgbuf, sizeof (msgbuf), "%s: %s\n", name, msg);
23445916cd2Sjpk 		(void) wdwmsg(name, msgbuf);
23545916cd2Sjpk 	} else {
2367c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: %s\n", name, msg);
2377c478bd9Sstevel@tonic-gate 		(void) fflush(stderr);
2387c478bd9Sstevel@tonic-gate 	}
23945916cd2Sjpk }
2407c478bd9Sstevel@tonic-gate 
2417c478bd9Sstevel@tonic-gate char *newenv[] = {"PATH=/usr/bin:/usr/sbin",
2427c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_ALL		*/
2437c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_COLLATE	*/
2447c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_CTYPE		*/
2457c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_MESSAGES	*/
2467c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_NUMERIC	*/
2477c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_TIME		*/
2487c478bd9Sstevel@tonic-gate 			NULL,			/* for LANG		*/
2497c478bd9Sstevel@tonic-gate 			NULL
2507c478bd9Sstevel@tonic-gate };
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate static char *
2537c478bd9Sstevel@tonic-gate getenvent(char *name, char *env[])
2547c478bd9Sstevel@tonic-gate {
2557c478bd9Sstevel@tonic-gate 	for (; *env != NULL; env++) {
2567c478bd9Sstevel@tonic-gate 		if (strncmp(*env, name, strlen(name)) == 0)
2577c478bd9Sstevel@tonic-gate 			return (*env);
2587c478bd9Sstevel@tonic-gate 	}
2597c478bd9Sstevel@tonic-gate 	return (NULL);
2607c478bd9Sstevel@tonic-gate }
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate int
2637c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char *envp[])
2647c478bd9Sstevel@tonic-gate {
2657c478bd9Sstevel@tonic-gate 	char		*name, *env;
26640e2b7c9Spaulson 	int		func = -1, optflg = 0, error = 0, c;
26745916cd2Sjpk 	zoneid_t	zoneid;
26845916cd2Sjpk 	uid_t		uid;
26945916cd2Sjpk 	char		*uname = NULL, *device = NULL, *zonename = NULL;
27045916cd2Sjpk 	char		*zname;
27145916cd2Sjpk 	char		pw_buf[NSS_BUFLEN_PASSWD];
27245916cd2Sjpk 	struct passwd	pw_ent;
2737c478bd9Sstevel@tonic-gate 	int 		env_num = 1;	/* PATH= is 0 entry */
274*facf4a8dSllai1 #ifdef DEBUG
275*facf4a8dSllai1 	struct stat	statbuf;
276*facf4a8dSllai1 #endif
2777c478bd9Sstevel@tonic-gate 
2787c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2797c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2807c478bd9Sstevel@tonic-gate 
28145916cd2Sjpk 	system_labeled = is_system_labeled();
28245916cd2Sjpk 
283*facf4a8dSllai1 	/* test hook: see also mkdevalloc.c and devfsadm.c */
284*facf4a8dSllai1 	if (!system_labeled) {
285*facf4a8dSllai1 		system_labeled = is_system_labeled_debug(&statbuf);
286*facf4a8dSllai1 		if (system_labeled) {
287*facf4a8dSllai1 			fprintf(stderr, "/ALLOCATE_FORCE_LABEL is set,\n"
288*facf4a8dSllai1 			    "forcing system label on for testing...\n");
289*facf4a8dSllai1 		}
290*facf4a8dSllai1 	}
291*facf4a8dSllai1 
2927c478bd9Sstevel@tonic-gate 	/*
2937c478bd9Sstevel@tonic-gate 	 * get all enviroment variables
2947c478bd9Sstevel@tonic-gate 	 * which affect on internationalization.
2957c478bd9Sstevel@tonic-gate 	 */
2967c478bd9Sstevel@tonic-gate 	env = getenvent("LC_ALL=", envp);
2977c478bd9Sstevel@tonic-gate 	if (env != NULL)
2987c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
2997c478bd9Sstevel@tonic-gate 	env = getenvent("LC_COLLATE=", envp);
3007c478bd9Sstevel@tonic-gate 	if (env != NULL)
3017c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
3027c478bd9Sstevel@tonic-gate 	env = getenvent("LC_CTYPE=", envp);
3037c478bd9Sstevel@tonic-gate 	if (env != NULL)
3047c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
3057c478bd9Sstevel@tonic-gate 	env = getenvent("LC_MESSAGES=", envp);
3067c478bd9Sstevel@tonic-gate 	if (env != NULL)
3077c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
3087c478bd9Sstevel@tonic-gate 	env = getenvent("LC_NUMERIC=", envp);
3097c478bd9Sstevel@tonic-gate 	if (env != NULL)
3107c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
3117c478bd9Sstevel@tonic-gate 	env = getenvent("LC_TIME=", envp);
3127c478bd9Sstevel@tonic-gate 	if (env != NULL)
3137c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
3147c478bd9Sstevel@tonic-gate 	env = getenvent("LANG=", envp);
3157c478bd9Sstevel@tonic-gate 	if (env != NULL)
3167c478bd9Sstevel@tonic-gate 		newenv[env_num] = env;
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	if ((name = strrchr(argv[0], '/')) == NULL)
3197c478bd9Sstevel@tonic-gate 		name = argv[0];
3207c478bd9Sstevel@tonic-gate 	else
3217c478bd9Sstevel@tonic-gate 		name++;
3227c478bd9Sstevel@tonic-gate 
32345916cd2Sjpk 	if (strcmp(name, ALLOC) == 0)
3247c478bd9Sstevel@tonic-gate 		func = 0;
32545916cd2Sjpk 	else if (strcmp(name, DEALLOC) == 0)
3267c478bd9Sstevel@tonic-gate 		func = 1;
32745916cd2Sjpk 	else if (strcmp(name, LIST) == 0)
3287c478bd9Sstevel@tonic-gate 		func = 2;
32945916cd2Sjpk 	else
33045916cd2Sjpk 		usage(-1);
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate 	audit_allocate_argv(func, argc, argv);
3337c478bd9Sstevel@tonic-gate 
33445916cd2Sjpk 	if (system_labeled) {
33545916cd2Sjpk 		/*
33645916cd2Sjpk 		 * allocate, deallocate, list_devices run in
33745916cd2Sjpk 		 * global zone only.
33845916cd2Sjpk 		 */
33945916cd2Sjpk 		zoneid = getzoneid();
34045916cd2Sjpk 		if (zoneid != GLOBAL_ZONEID)
34145916cd2Sjpk 			exit(GLOBALERR);
34245916cd2Sjpk 		zname = GLOBAL_ZONENAME;
34345916cd2Sjpk 		/*
34445916cd2Sjpk 		 * check if device allocation is activated.
34545916cd2Sjpk 		 */
34645916cd2Sjpk 		if (da_is_on() == 0) {
34745916cd2Sjpk 			(void) fprintf(stderr, "%s%s",
34845916cd2Sjpk 			    gettext("Turn device allocation on"),
34945916cd2Sjpk 			    gettext(" to use this feature.\n"));
35045916cd2Sjpk 			exit(DAOFFERR);
35145916cd2Sjpk 		}
35245916cd2Sjpk 	}
35345916cd2Sjpk 
35440e2b7c9Spaulson 	if (func == 0) {	/* allocate */
35545916cd2Sjpk 		while ((c = getopt(argc, argv, "gswz:FU:")) != -1) {
35640e2b7c9Spaulson 			switch (c) {
35745916cd2Sjpk 			case 'g':
35845916cd2Sjpk 				optflg |= TYPE;
35945916cd2Sjpk 				break;
36040e2b7c9Spaulson 			case 's':
36140e2b7c9Spaulson 				optflg |= SILENT;
36240e2b7c9Spaulson 				break;
36345916cd2Sjpk 			case 'w':
36445916cd2Sjpk 				if (system_labeled) {
36545916cd2Sjpk 					optflg |= WINDOWING;
36645916cd2Sjpk 					windowing = 1;
36745916cd2Sjpk 				} else {
36845916cd2Sjpk 					usage(func);
36945916cd2Sjpk 				}
37045916cd2Sjpk 				break;
37145916cd2Sjpk 			case 'z':
37245916cd2Sjpk 				if (system_labeled) {
37345916cd2Sjpk 					optflg |= ZONENAME;
37445916cd2Sjpk 					zonename = optarg;
37545916cd2Sjpk 				} else {
37645916cd2Sjpk 					usage(func);
37745916cd2Sjpk 				}
37845916cd2Sjpk 				break;
37945916cd2Sjpk 			case 'F':
38045916cd2Sjpk 				optflg |= FORCE;
38145916cd2Sjpk 				break;
38240e2b7c9Spaulson 			case 'U':
38340e2b7c9Spaulson 				optflg |= USERNAME;
38440e2b7c9Spaulson 				uname = optarg;
38540e2b7c9Spaulson 				break;
38640e2b7c9Spaulson 			case '?':
38740e2b7c9Spaulson 			default :
38840e2b7c9Spaulson 				usage(func);
38940e2b7c9Spaulson 			}
39040e2b7c9Spaulson 		}
39140e2b7c9Spaulson 
39240e2b7c9Spaulson 		/*
39340e2b7c9Spaulson 		 * allocate(1) must be supplied with one device argument
39440e2b7c9Spaulson 		 */
39540e2b7c9Spaulson 		if ((argc - optind) != 1) {
39640e2b7c9Spaulson 			usage(func);
39740e2b7c9Spaulson 		} else {
39840e2b7c9Spaulson 			device = argv[optind];
39940e2b7c9Spaulson 		}
40040e2b7c9Spaulson 	}
40140e2b7c9Spaulson 
40240e2b7c9Spaulson 	else if (func == 1) {	/* deallocate */
40345916cd2Sjpk 		while ((c = getopt(argc, argv, "gswz:FI")) != -1) {
40440e2b7c9Spaulson 			switch (c) {
40545916cd2Sjpk 			case 'g':
40645916cd2Sjpk 				if (system_labeled)
40745916cd2Sjpk 					optflg |= TYPE;
40845916cd2Sjpk 				else
40945916cd2Sjpk 					usage(func);
41045916cd2Sjpk 				break;
41140e2b7c9Spaulson 			case 's':
41240e2b7c9Spaulson 				optflg |= SILENT;
41340e2b7c9Spaulson 				break;
41445916cd2Sjpk 			case 'w':
41545916cd2Sjpk 				if (system_labeled) {
41645916cd2Sjpk 					optflg |= WINDOWING;
41745916cd2Sjpk 					windowing = 1;
41845916cd2Sjpk 				} else {
41945916cd2Sjpk 					usage(func);
42045916cd2Sjpk 				}
42145916cd2Sjpk 				break;
42245916cd2Sjpk 			case 'z':
42345916cd2Sjpk 				if (system_labeled) {
42445916cd2Sjpk 					optflg |= ZONENAME;
42545916cd2Sjpk 					zonename = optarg;
42645916cd2Sjpk 				} else {
42745916cd2Sjpk 					usage(func);
42845916cd2Sjpk 				}
42945916cd2Sjpk 				break;
43040e2b7c9Spaulson 			case 'F':
43140e2b7c9Spaulson 				optflg |= FORCE;
43240e2b7c9Spaulson 				break;
43340e2b7c9Spaulson 			case 'I':
43440e2b7c9Spaulson 				optflg |= FORCE_ALL;
43540e2b7c9Spaulson 				break;
43640e2b7c9Spaulson 			case '?':
43740e2b7c9Spaulson 			default :
43840e2b7c9Spaulson 				usage(func);
43940e2b7c9Spaulson 			}
44040e2b7c9Spaulson 		}
44140e2b7c9Spaulson 
44240e2b7c9Spaulson 		if ((optflg & FORCE) && (optflg & FORCE_ALL))
44340e2b7c9Spaulson 			usage(func);
44440e2b7c9Spaulson 
44545916cd2Sjpk 		if (system_labeled && ((optflg & FORCE_ALL) && (optflg & TYPE)))
44645916cd2Sjpk 			usage(func);
44745916cd2Sjpk 
44840e2b7c9Spaulson 		/*
44940e2b7c9Spaulson 		 * deallocate(1) must be supplied with one device
45040e2b7c9Spaulson 		 * argument unless the '-I' argument is supplied
45140e2b7c9Spaulson 		 */
45240e2b7c9Spaulson 		if (!(optflg & FORCE_ALL)) {
45340e2b7c9Spaulson 			if ((argc - optind) != 1) {
45440e2b7c9Spaulson 				usage(func);
45540e2b7c9Spaulson 			} else {
45640e2b7c9Spaulson 				device = argv[optind];
45740e2b7c9Spaulson 			}
45840e2b7c9Spaulson 		} else {
45940e2b7c9Spaulson 			if ((argc - optind) >= 1) {
46040e2b7c9Spaulson 				usage(func);
46140e2b7c9Spaulson 			}
46240e2b7c9Spaulson 		}
46340e2b7c9Spaulson 	}
46440e2b7c9Spaulson 
46540e2b7c9Spaulson 	else if (func == 2) {	/* list_devices */
46645916cd2Sjpk 		while ((c = getopt(argc, argv, "adlnsuwz:U:")) != -1) {
4677c478bd9Sstevel@tonic-gate 			switch (c) {
46845916cd2Sjpk 			case 'a':
46945916cd2Sjpk 				if (system_labeled) {
47045916cd2Sjpk 					/*
47145916cd2Sjpk 					 * list auths, cleaning programs,
47245916cd2Sjpk 					 * labels.
47345916cd2Sjpk 					 */
47445916cd2Sjpk 					optflg |= LISTATTRS;
47545916cd2Sjpk 				} else {
47645916cd2Sjpk 					usage(func);
47745916cd2Sjpk 				}
47845916cd2Sjpk 				break;
47945916cd2Sjpk 			case 'd':
48045916cd2Sjpk 				if (system_labeled) {
48145916cd2Sjpk 					/*
48245916cd2Sjpk 					 * list devalloc_defaults
48345916cd2Sjpk 					 */
48445916cd2Sjpk 					optflg |= LISTDEFS;
48545916cd2Sjpk 				} else {
48645916cd2Sjpk 					usage(func);
48745916cd2Sjpk 				}
48845916cd2Sjpk 				break;
48945916cd2Sjpk 			case 'l':
49045916cd2Sjpk 				optflg |= LISTALL;
49145916cd2Sjpk 				break;
49245916cd2Sjpk 			case 'n':
49345916cd2Sjpk 				optflg |= LISTFREE;
49445916cd2Sjpk 				break;
4957c478bd9Sstevel@tonic-gate 			case 's':
4967c478bd9Sstevel@tonic-gate 				optflg |= SILENT;
4977c478bd9Sstevel@tonic-gate 				break;
49845916cd2Sjpk 			case 'u':
49945916cd2Sjpk 				optflg |= LISTALLOC;
50045916cd2Sjpk 				break;
50145916cd2Sjpk 			case 'w':
50245916cd2Sjpk 				if (system_labeled) {
50345916cd2Sjpk 					/*
50445916cd2Sjpk 					 * Private interface for use by
50545916cd2Sjpk 					 * list_devices GUI
50645916cd2Sjpk 					 */
50745916cd2Sjpk 					optflg |= WINDOWING;
50845916cd2Sjpk 				} else {
50945916cd2Sjpk 					usage(func);
51045916cd2Sjpk 				}
51145916cd2Sjpk 				break;
51245916cd2Sjpk 			case 'z':
51345916cd2Sjpk 				if (system_labeled) {
51445916cd2Sjpk 					optflg |= ZONENAME;
51545916cd2Sjpk 					zonename = optarg;
51645916cd2Sjpk 				} else {
51745916cd2Sjpk 					usage(func);
51845916cd2Sjpk 				}
51945916cd2Sjpk 				break;
5207c478bd9Sstevel@tonic-gate 			case 'U':
5217c478bd9Sstevel@tonic-gate 				optflg |= USERID;
52240e2b7c9Spaulson 				uid = atoi(optarg);
5237c478bd9Sstevel@tonic-gate 				break;
5247c478bd9Sstevel@tonic-gate 			case '?':
5257c478bd9Sstevel@tonic-gate 			default :
5267c478bd9Sstevel@tonic-gate 				usage(func);
52740e2b7c9Spaulson 			}
5287c478bd9Sstevel@tonic-gate 		}
5297c478bd9Sstevel@tonic-gate 
53045916cd2Sjpk 		if (system_labeled) {
53145916cd2Sjpk 			if (((optflg & LISTALL) && (optflg & LISTFREE)) ||
53245916cd2Sjpk 			    ((optflg & LISTALL) && (optflg & LISTALLOC)) ||
53345916cd2Sjpk 			    ((optflg & LISTFREE) && (optflg & LISTALLOC)) ||
53445916cd2Sjpk 			    ((optflg & LISTDEFS) &&
53545916cd2Sjpk 			    (optflg & (LISTATTRS | LISTALL | LISTFREE |
53645916cd2Sjpk 			    LISTALLOC | USERID | WINDOWING | ZONENAME))) ||
53745916cd2Sjpk 			    (!(optflg & (LISTALL | LISTFREE | LISTALLOC |
53845916cd2Sjpk 			    LISTDEFS | WINDOWING))))
53940e2b7c9Spaulson 				usage(func);
54045916cd2Sjpk 		} else if (((optflg & LISTALL) && (optflg & LISTFREE)) ||
54145916cd2Sjpk 		    ((optflg & LISTALL) && (optflg & LISTALLOC)) ||
54245916cd2Sjpk 		    ((optflg & LISTFREE) && (optflg & LISTALLOC)) ||
54345916cd2Sjpk 		    (!(optflg & (LISTALL | LISTFREE | LISTALLOC)))) {
54445916cd2Sjpk 			usage(func);
54545916cd2Sjpk 		}
54640e2b7c9Spaulson 
54740e2b7c9Spaulson 		/*
54840e2b7c9Spaulson 		 * list_devices(1) takes an optional device argument
54940e2b7c9Spaulson 		 */
55040e2b7c9Spaulson 		if ((argc - optind) == 1) {
55140e2b7c9Spaulson 			device = argv[optind];
55240e2b7c9Spaulson 		} else {
55340e2b7c9Spaulson 			if ((argc - optind) > 1) {
55440e2b7c9Spaulson 				usage(func);
55540e2b7c9Spaulson 			}
55640e2b7c9Spaulson 		}
55740e2b7c9Spaulson 	}
55840e2b7c9Spaulson 
55940e2b7c9Spaulson 	if (optflg & USERNAME) {
56045916cd2Sjpk 		if (getpwnam_r(uname, &pw_ent, pw_buf, sizeof (pw_buf)) ==
56145916cd2Sjpk 		    NULL) {
56245916cd2Sjpk 			(void) fprintf(stderr,
56345916cd2Sjpk 			    gettext("Invalid user name -- %s -- \n"), uname);
56440e2b7c9Spaulson 			exit(1);
56540e2b7c9Spaulson 		}
56645916cd2Sjpk 		uid = pw_ent.pw_uid;
56745916cd2Sjpk 	} else if (optflg & USERID) {
56845916cd2Sjpk 		if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL) {
56945916cd2Sjpk 			(void) fprintf(stderr,
57045916cd2Sjpk 			    gettext("Invalid user ID -- %d -- \n"), uid);
57140e2b7c9Spaulson 			exit(1);
5727c478bd9Sstevel@tonic-gate 		}
57345916cd2Sjpk 		uid = pw_ent.pw_uid;
57445916cd2Sjpk 	} else {
57545916cd2Sjpk 		/*
57645916cd2Sjpk 		 * caller's uid is the default if no user specified.
57745916cd2Sjpk 		 */
57845916cd2Sjpk 		uid = getuid();
5797c478bd9Sstevel@tonic-gate 	}
5807c478bd9Sstevel@tonic-gate 
58145916cd2Sjpk 	/*
58245916cd2Sjpk 	 * global zone is the default if no zonename specified.
58345916cd2Sjpk 	 */
58445916cd2Sjpk 	if (zonename == NULL) {
58545916cd2Sjpk 		zonename = zname;
58645916cd2Sjpk 	} else {
58745916cd2Sjpk 		if (zone_get_id(zonename, &zoneid) != 0) {
58845916cd2Sjpk 			(void) fprintf(stderr,
58945916cd2Sjpk 			    gettext("Invalid zone name -- %s -- \n"), zonename);
59045916cd2Sjpk 			exit(1);
5917c478bd9Sstevel@tonic-gate 		}
59245916cd2Sjpk 	}
59345916cd2Sjpk 
59445916cd2Sjpk 	if (func == 0)
59545916cd2Sjpk 		error = allocate(optflg, uid, device, zonename);
59645916cd2Sjpk 	else if (func == 1)
59745916cd2Sjpk 		error = deallocate(optflg, uid, device, zonename);
59845916cd2Sjpk 	else if (func == 2)
59945916cd2Sjpk 		error = list_devices(optflg, uid, device, zonename);
60040e2b7c9Spaulson 
6017c478bd9Sstevel@tonic-gate 	(void) audit_allocate_record(error);
6027c478bd9Sstevel@tonic-gate 
6037c478bd9Sstevel@tonic-gate 	if (error) {
6047c478bd9Sstevel@tonic-gate 		if (!(optflg & SILENT))
6057c478bd9Sstevel@tonic-gate 			print_error(error, name);
6067c478bd9Sstevel@tonic-gate 		exit(error);
6077c478bd9Sstevel@tonic-gate 	}
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	return (0);
6107c478bd9Sstevel@tonic-gate }
61145916cd2Sjpk 
61245916cd2Sjpk /*
61345916cd2Sjpk  * Display error message via /etc/security/lib/wdwmsg script
61445916cd2Sjpk  */
61545916cd2Sjpk static int
61645916cd2Sjpk wdwmsg(char *name, char *msg)
61745916cd2Sjpk {
61845916cd2Sjpk 	pid_t child_pid;
61945916cd2Sjpk 	pid_t wait_pid;
62045916cd2Sjpk 	int child_status;
62145916cd2Sjpk 
62245916cd2Sjpk 	/* Fork a child */
62345916cd2Sjpk 	switch (child_pid = fork()) {
62445916cd2Sjpk 	case -1:	/* FAILURE */
62545916cd2Sjpk 		return (-1);
62645916cd2Sjpk 		break;
62745916cd2Sjpk 
62845916cd2Sjpk 	case 0:		/* CHILD */
62945916cd2Sjpk 		(void) execl("/etc/security/lib/wdwmsg", "wdwmsg", msg,
63045916cd2Sjpk 		    name, "OK", NULL);
63145916cd2Sjpk 		/* If exec failed, send message to stderr */
63245916cd2Sjpk 		(void) fprintf(stderr, "%s", msg);
63345916cd2Sjpk 		return (-1);
63445916cd2Sjpk 
63545916cd2Sjpk 	default:	/* PARENT */
63645916cd2Sjpk 		/* Wait for child to exit */
63745916cd2Sjpk 		wait_pid = waitpid(child_pid, &child_status, 0);
63845916cd2Sjpk 		if ((wait_pid < 0) && (errno == ECHILD))
63945916cd2Sjpk 			return (0);
64045916cd2Sjpk 		if ((wait_pid < 0) || (wait_pid != child_pid))
64145916cd2Sjpk 			return (-1);
64245916cd2Sjpk 		if (WIFEXITED(child_status))
64345916cd2Sjpk 			return (WEXITSTATUS(child_status));
64445916cd2Sjpk 		if (WIFSIGNALED(child_status))
64545916cd2Sjpk 			return (WTERMSIG(child_status));
64645916cd2Sjpk 		return (0);
64745916cd2Sjpk 	}
64845916cd2Sjpk }
649