xref: /titanic_44/usr/src/cmd/allocate/allocate.c (revision 45916cd2fec6e79bca5dee0421bd39e3c2910d1e)
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
5*45916cd2Sjpk  * Common Development and Distribution License (the "License").
6*45916cd2Sjpk  * 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  */
21*45916cd2Sjpk 
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>
36*45916cd2Sjpk #include <ctype.h>
37*45916cd2Sjpk #include <nss_dbdefs.h>
387c478bd9Sstevel@tonic-gate #include <sys/types.h>
39*45916cd2Sjpk #include <sys/wait.h>
40*45916cd2Sjpk #include <tsol/label.h>
41*45916cd2Sjpk #include <zone.h>
42*45916cd2Sjpk #include <bsm/devalloc.h>
437c478bd9Sstevel@tonic-gate #include "allocate.h"
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate #if !defined(TEXT_DOMAIN)
467c478bd9Sstevel@tonic-gate #define	TEXT_DOMAIN "SUNW_OST_OSCMD"
477c478bd9Sstevel@tonic-gate #endif
487c478bd9Sstevel@tonic-gate 
49*45916cd2Sjpk #define	ALLOC	"allocate"
50*45916cd2Sjpk #define	DEALLOC	"deallocate"
51*45916cd2Sjpk #define	LIST	"list_devices"
52*45916cd2Sjpk 
537c478bd9Sstevel@tonic-gate extern void audit_allocate_argv(int, int, char *[]);
547c478bd9Sstevel@tonic-gate extern int audit_allocate_record(int);
557c478bd9Sstevel@tonic-gate 
56*45916cd2Sjpk int system_labeled = 0;
57*45916cd2Sjpk static int windowing = 0;
58*45916cd2Sjpk static int wdwmsg(char *name, char *msg);
59*45916cd2Sjpk 
607c478bd9Sstevel@tonic-gate static void
617c478bd9Sstevel@tonic-gate usage(int func)
627c478bd9Sstevel@tonic-gate {
63*45916cd2Sjpk 	if (system_labeled) {
64*45916cd2Sjpk 		char *use[9];
65*45916cd2Sjpk 
66*45916cd2Sjpk 		use[0] = gettext("allocate [-s] [-w] [-U uname] [-z zonename] "
67*45916cd2Sjpk 		    "[-F] device");
68*45916cd2Sjpk 		use[1] = gettext("allocate [-s] [-w] [-U uname] [-z zonename] "
69*45916cd2Sjpk 		    "[-F] -g dev_type");
70*45916cd2Sjpk 		use[2] = gettext("deallocate [-s] [-w] [-z zonename] "
71*45916cd2Sjpk 		    "[-F] device");
72*45916cd2Sjpk 		use[3] = gettext("deallocate [-s] [-w] [-z zonename] "
73*45916cd2Sjpk 		    "[-F] -g dev_type");
74*45916cd2Sjpk 		use[4] = gettext("deallocate [-s] [-w] [-z zonename] -I");
75*45916cd2Sjpk 		use[5] = gettext("list_devices [-s] [-U uid] [-z zonename] "
76*45916cd2Sjpk 		    "[-a] -l [device]");
77*45916cd2Sjpk 		use[6] = gettext("list_devices [-s] [-U uid] [-z zonename] "
78*45916cd2Sjpk 		    "[-a] -n [device]");
79*45916cd2Sjpk 		use[7] = gettext("list_devices [-s] [-U uid] [-z zonename] "
80*45916cd2Sjpk 		    "[-a] -u [device]");
81*45916cd2Sjpk 		use[8] = gettext("list_devices [-s] -d dev_type");
82*45916cd2Sjpk 
83*45916cd2Sjpk 		switch (func) {
84*45916cd2Sjpk 			case 0:
85*45916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n",
86*45916cd2Sjpk 				    use[0], use[1]);
87*45916cd2Sjpk 				break;
88*45916cd2Sjpk 			case 1:
89*45916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n%s\n",
90*45916cd2Sjpk 				    use[2], use[3], use[4]);
91*45916cd2Sjpk 				break;
92*45916cd2Sjpk 			case 2:
93*45916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n%s\n%s\n",
94*45916cd2Sjpk 				    use[5], use[6], use[7], use[8]);
95*45916cd2Sjpk 				break;
96*45916cd2Sjpk 			default:
97*45916cd2Sjpk 				(void) fprintf(stderr,
98*45916cd2Sjpk 				    "%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
99*45916cd2Sjpk 				    use[0], use[1], use[2], use[3], use[4],
100*45916cd2Sjpk 				    use[5], use[6], use[7], use[8]);
101*45916cd2Sjpk 		}
102*45916cd2Sjpk 	} else {
10340e2b7c9Spaulson 		char *use[7];
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate 		use[0] = gettext("allocate [-s] [-U uname] [-F] device");
1067c478bd9Sstevel@tonic-gate 		use[1] = gettext("allocate [-s] [-U uname] -g dev_type");
1077c478bd9Sstevel@tonic-gate 		use[2] = gettext("deallocate [-s] [-F] device");
10840e2b7c9Spaulson 		use[3] = gettext("deallocate [-s] -I");
10940e2b7c9Spaulson 		use[4] = gettext("list_devices [-s] [-U uid] -l [device]");
11040e2b7c9Spaulson 		use[5] = gettext("list_devices [-s] [-U uid] -n [device]");
11140e2b7c9Spaulson 		use[6] = gettext("list_devices [-s] [-U uid] -u [device]");
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 		switch (func) {
1147c478bd9Sstevel@tonic-gate 			case 0:
115*45916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n",
116*45916cd2Sjpk 				    use[0], use[1]);
1177c478bd9Sstevel@tonic-gate 				break;
1187c478bd9Sstevel@tonic-gate 			case 1:
119*45916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n",
120*45916cd2Sjpk 				    use[2], use[3]);
1217c478bd9Sstevel@tonic-gate 				break;
1227c478bd9Sstevel@tonic-gate 			case 2:
123*45916cd2Sjpk 				(void) fprintf(stderr, "%s\n%s\n%s\n",
124*45916cd2Sjpk 				    use[4], use[5], use[6]);
1257c478bd9Sstevel@tonic-gate 				break;
1267c478bd9Sstevel@tonic-gate 			default:
127*45916cd2Sjpk 				(void) fprintf(stderr,
128*45916cd2Sjpk 				    "%s\n%s\n%s\n%s\n%s\n%s\n%s\n",
129*45916cd2Sjpk 					use[0], use[1], use[2], use[3], use[4],
130*45916cd2Sjpk 					use[5], use[6]);
131*45916cd2Sjpk 		}
1327c478bd9Sstevel@tonic-gate 	}
13340e2b7c9Spaulson 	exit(1);
1347c478bd9Sstevel@tonic-gate }
1357c478bd9Sstevel@tonic-gate 
136*45916cd2Sjpk void
1377c478bd9Sstevel@tonic-gate print_error(int error, char *name)
1387c478bd9Sstevel@tonic-gate {
1397c478bd9Sstevel@tonic-gate 	char	*msg;
140*45916cd2Sjpk 	char	msgbuf[200];
1417c478bd9Sstevel@tonic-gate 
1427c478bd9Sstevel@tonic-gate 	switch (error) {
143*45916cd2Sjpk 	case ALLOCUERR:
1447c478bd9Sstevel@tonic-gate 		msg = gettext("Specified device is allocated to another user.");
1457c478bd9Sstevel@tonic-gate 		break;
146*45916cd2Sjpk 	case CHOWNERR:
147*45916cd2Sjpk 		msg = gettext("Failed to chown.");
1487c478bd9Sstevel@tonic-gate 		break;
149*45916cd2Sjpk 	case CLEANERR:
150*45916cd2Sjpk 		msg = gettext("Unable to clean up device.");
1517c478bd9Sstevel@tonic-gate 		break;
152*45916cd2Sjpk 	case CNTDEXECERR:
1537c478bd9Sstevel@tonic-gate 		msg = gettext(
1547c478bd9Sstevel@tonic-gate 		    "Can't exec device-clean program for specified device.");
1557c478bd9Sstevel@tonic-gate 		break;
156*45916cd2Sjpk 	case CNTFRCERR:
157*45916cd2Sjpk 		msg = gettext("Can't force deallocate specified device.");
1587c478bd9Sstevel@tonic-gate 		break;
159*45916cd2Sjpk 	case DACACCERR:
160*45916cd2Sjpk 		msg = gettext(
161*45916cd2Sjpk 		    "Can't access DAC file for the device specified.");
162*45916cd2Sjpk 		break;
163*45916cd2Sjpk 	case DAOFFERR:
164*45916cd2Sjpk 		msg = gettext(
165*45916cd2Sjpk 		    "Device allocation feature is not activated "
166*45916cd2Sjpk 		    "on this system.");
167*45916cd2Sjpk 		break;
168*45916cd2Sjpk 	case DAUTHERR:
169*45916cd2Sjpk 		msg = gettext("Device not allocatable.");
170*45916cd2Sjpk 		break;
171*45916cd2Sjpk 	case DEFATTRSERR:
172*45916cd2Sjpk 		msg = gettext("No default attributes for specified "
173*45916cd2Sjpk 		    "device type.");
174*45916cd2Sjpk 		break;
175*45916cd2Sjpk 	case DEVLKERR:
176*45916cd2Sjpk 		msg = gettext("Concurrent operations for specified device, "
177*45916cd2Sjpk 		    "try later.");
178*45916cd2Sjpk 		break;
179*45916cd2Sjpk 	case DEVLONGERR:
180*45916cd2Sjpk 		msg = gettext("Device name is too long.");
181*45916cd2Sjpk 		break;
182*45916cd2Sjpk 	case DEVNALLOCERR:
183*45916cd2Sjpk 		msg = gettext("Device not allocated.");
184*45916cd2Sjpk 		break;
185*45916cd2Sjpk 	case DEVNAMEERR:
186*45916cd2Sjpk 		msg = gettext("Device name error.");
187*45916cd2Sjpk 		break;
188*45916cd2Sjpk 	case DEVSTATEERR:
189*45916cd2Sjpk 		msg = gettext("Device specified is in allocate error state.");
190*45916cd2Sjpk 		break;
191*45916cd2Sjpk 	case DEVZONEERR:
192*45916cd2Sjpk 		msg = gettext("Can't find name of the zone to which "
193*45916cd2Sjpk 		    "device is allocated.");
194*45916cd2Sjpk 		break;
195*45916cd2Sjpk 	case DSPMISSERR:
1967c478bd9Sstevel@tonic-gate 		msg = gettext(
1977c478bd9Sstevel@tonic-gate 		    "Device special file(s) missing for specified device.");
1987c478bd9Sstevel@tonic-gate 		break;
199*45916cd2Sjpk 	case LABELRNGERR:
200*45916cd2Sjpk 		msg = gettext(
201*45916cd2Sjpk 		    "Operation inconsistent with device's label range.");
2027c478bd9Sstevel@tonic-gate 		break;
203*45916cd2Sjpk 	case LOGINDEVPERMERR:
204*45916cd2Sjpk 		msg = gettext("Device controlled by logindevperm(4)");
2057c478bd9Sstevel@tonic-gate 		break;
206*45916cd2Sjpk 	case NODAERR:
207*45916cd2Sjpk 		msg = gettext("No entry for specified device.");
208*45916cd2Sjpk 		break;
209*45916cd2Sjpk 	case NODMAPERR:
210*45916cd2Sjpk 		msg = gettext("No entry for specified device.");
211*45916cd2Sjpk 		break;
212*45916cd2Sjpk 	case PREALLOCERR:
2137c478bd9Sstevel@tonic-gate 		msg = gettext("Device already allocated.");
2147c478bd9Sstevel@tonic-gate 		break;
215*45916cd2Sjpk 	case SETACLERR:
216*45916cd2Sjpk 		msg = gettext("Failed to set ACL.");
2177c478bd9Sstevel@tonic-gate 		break;
218*45916cd2Sjpk 	case UAUTHERR:
219*45916cd2Sjpk 		msg = gettext(
220*45916cd2Sjpk 		    "User lacks authorization required for this operation.");
2217c478bd9Sstevel@tonic-gate 		break;
222*45916cd2Sjpk 	case ZONEERR:
223*45916cd2Sjpk 		msg = gettext("Failed to configure device in zone.");
2247c478bd9Sstevel@tonic-gate 		break;
2257c478bd9Sstevel@tonic-gate 	default:
2267c478bd9Sstevel@tonic-gate 		msg = gettext("Unknown error code.");
2277c478bd9Sstevel@tonic-gate 		break;
2287c478bd9Sstevel@tonic-gate 	}
2297c478bd9Sstevel@tonic-gate 
230*45916cd2Sjpk 	if (windowing) {
231*45916cd2Sjpk 		(void) snprintf(msgbuf, sizeof (msgbuf), "%s: %s\n", name, msg);
232*45916cd2Sjpk 		(void) wdwmsg(name, msgbuf);
233*45916cd2Sjpk 	} else {
2347c478bd9Sstevel@tonic-gate 		(void) fprintf(stderr, "%s: %s\n", name, msg);
2357c478bd9Sstevel@tonic-gate 		(void) fflush(stderr);
2367c478bd9Sstevel@tonic-gate 	}
237*45916cd2Sjpk }
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate char *newenv[] = {"PATH=/usr/bin:/usr/sbin",
2407c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_ALL		*/
2417c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_COLLATE	*/
2427c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_CTYPE		*/
2437c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_MESSAGES	*/
2447c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_NUMERIC	*/
2457c478bd9Sstevel@tonic-gate 			NULL,			/* for LC_TIME		*/
2467c478bd9Sstevel@tonic-gate 			NULL,			/* for LANG		*/
2477c478bd9Sstevel@tonic-gate 			NULL
2487c478bd9Sstevel@tonic-gate };
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate static char *
2517c478bd9Sstevel@tonic-gate getenvent(char *name, char *env[])
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate 	for (; *env != NULL; env++) {
2547c478bd9Sstevel@tonic-gate 		if (strncmp(*env, name, strlen(name)) == 0)
2557c478bd9Sstevel@tonic-gate 			return (*env);
2567c478bd9Sstevel@tonic-gate 	}
2577c478bd9Sstevel@tonic-gate 	return (NULL);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate int
2617c478bd9Sstevel@tonic-gate main(int argc, char *argv[], char *envp[])
2627c478bd9Sstevel@tonic-gate {
2637c478bd9Sstevel@tonic-gate 	char		*name, *env;
26440e2b7c9Spaulson 	int		func = -1, optflg = 0, error = 0, c;
265*45916cd2Sjpk 	zoneid_t	zoneid;
266*45916cd2Sjpk 	uid_t		uid;
267*45916cd2Sjpk 	char		*uname = NULL, *device = NULL, *zonename = NULL;
268*45916cd2Sjpk 	char		*zname;
269*45916cd2Sjpk 	char		pw_buf[NSS_BUFLEN_PASSWD];
270*45916cd2Sjpk 	struct passwd	pw_ent;
2717c478bd9Sstevel@tonic-gate 	int 		env_num = 1;	/* PATH= is 0 entry */
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 	(void) setlocale(LC_ALL, "");
2747c478bd9Sstevel@tonic-gate 	(void) textdomain(TEXT_DOMAIN);
2757c478bd9Sstevel@tonic-gate 
276*45916cd2Sjpk 	system_labeled = is_system_labeled();
277*45916cd2Sjpk 
2787c478bd9Sstevel@tonic-gate 	/*
2797c478bd9Sstevel@tonic-gate 	 * get all enviroment variables
2807c478bd9Sstevel@tonic-gate 	 * which affect on internationalization.
2817c478bd9Sstevel@tonic-gate 	 */
2827c478bd9Sstevel@tonic-gate 	env = getenvent("LC_ALL=", envp);
2837c478bd9Sstevel@tonic-gate 	if (env != NULL)
2847c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
2857c478bd9Sstevel@tonic-gate 	env = getenvent("LC_COLLATE=", envp);
2867c478bd9Sstevel@tonic-gate 	if (env != NULL)
2877c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
2887c478bd9Sstevel@tonic-gate 	env = getenvent("LC_CTYPE=", envp);
2897c478bd9Sstevel@tonic-gate 	if (env != NULL)
2907c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
2917c478bd9Sstevel@tonic-gate 	env = getenvent("LC_MESSAGES=", envp);
2927c478bd9Sstevel@tonic-gate 	if (env != NULL)
2937c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
2947c478bd9Sstevel@tonic-gate 	env = getenvent("LC_NUMERIC=", envp);
2957c478bd9Sstevel@tonic-gate 	if (env != NULL)
2967c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
2977c478bd9Sstevel@tonic-gate 	env = getenvent("LC_TIME=", envp);
2987c478bd9Sstevel@tonic-gate 	if (env != NULL)
2997c478bd9Sstevel@tonic-gate 		newenv[env_num++] = env;
3007c478bd9Sstevel@tonic-gate 	env = getenvent("LANG=", envp);
3017c478bd9Sstevel@tonic-gate 	if (env != NULL)
3027c478bd9Sstevel@tonic-gate 		newenv[env_num] = env;
3037c478bd9Sstevel@tonic-gate 
3047c478bd9Sstevel@tonic-gate 	if ((name = strrchr(argv[0], '/')) == NULL)
3057c478bd9Sstevel@tonic-gate 		name = argv[0];
3067c478bd9Sstevel@tonic-gate 	else
3077c478bd9Sstevel@tonic-gate 		name++;
3087c478bd9Sstevel@tonic-gate 
309*45916cd2Sjpk 	if (strcmp(name, ALLOC) == 0)
3107c478bd9Sstevel@tonic-gate 		func = 0;
311*45916cd2Sjpk 	else if (strcmp(name, DEALLOC) == 0)
3127c478bd9Sstevel@tonic-gate 		func = 1;
313*45916cd2Sjpk 	else if (strcmp(name, LIST) == 0)
3147c478bd9Sstevel@tonic-gate 		func = 2;
315*45916cd2Sjpk 	else
316*45916cd2Sjpk 		usage(-1);
3177c478bd9Sstevel@tonic-gate 
3187c478bd9Sstevel@tonic-gate 	audit_allocate_argv(func, argc, argv);
3197c478bd9Sstevel@tonic-gate 
320*45916cd2Sjpk 	if (system_labeled) {
321*45916cd2Sjpk 		/*
322*45916cd2Sjpk 		 * allocate, deallocate, list_devices run in
323*45916cd2Sjpk 		 * global zone only.
324*45916cd2Sjpk 		 */
325*45916cd2Sjpk 		zoneid = getzoneid();
326*45916cd2Sjpk 		if (zoneid != GLOBAL_ZONEID)
327*45916cd2Sjpk 			exit(GLOBALERR);
328*45916cd2Sjpk 		zname = GLOBAL_ZONENAME;
329*45916cd2Sjpk 		/*
330*45916cd2Sjpk 		 * check if device allocation is activated.
331*45916cd2Sjpk 		 */
332*45916cd2Sjpk 		if (da_is_on() == 0) {
333*45916cd2Sjpk 			(void) fprintf(stderr, "%s%s",
334*45916cd2Sjpk 			    gettext("Turn device allocation on"),
335*45916cd2Sjpk 			    gettext(" to use this feature.\n"));
336*45916cd2Sjpk 			exit(DAOFFERR);
337*45916cd2Sjpk 		}
338*45916cd2Sjpk 	}
339*45916cd2Sjpk 
34040e2b7c9Spaulson 	if (func == 0) {	/* allocate */
341*45916cd2Sjpk 		while ((c = getopt(argc, argv, "gswz:FU:")) != -1) {
34240e2b7c9Spaulson 			switch (c) {
343*45916cd2Sjpk 			case 'g':
344*45916cd2Sjpk 				optflg |= TYPE;
345*45916cd2Sjpk 				break;
34640e2b7c9Spaulson 			case 's':
34740e2b7c9Spaulson 				optflg |= SILENT;
34840e2b7c9Spaulson 				break;
349*45916cd2Sjpk 			case 'w':
350*45916cd2Sjpk 				if (system_labeled) {
351*45916cd2Sjpk 					optflg |= WINDOWING;
352*45916cd2Sjpk 					windowing = 1;
353*45916cd2Sjpk 				} else {
354*45916cd2Sjpk 					usage(func);
355*45916cd2Sjpk 				}
356*45916cd2Sjpk 				break;
357*45916cd2Sjpk 			case 'z':
358*45916cd2Sjpk 				if (system_labeled) {
359*45916cd2Sjpk 					optflg |= ZONENAME;
360*45916cd2Sjpk 					zonename = optarg;
361*45916cd2Sjpk 				} else {
362*45916cd2Sjpk 					usage(func);
363*45916cd2Sjpk 				}
364*45916cd2Sjpk 				break;
365*45916cd2Sjpk 			case 'F':
366*45916cd2Sjpk 				optflg |= FORCE;
367*45916cd2Sjpk 				break;
36840e2b7c9Spaulson 			case 'U':
36940e2b7c9Spaulson 				optflg |= USERNAME;
37040e2b7c9Spaulson 				uname = optarg;
37140e2b7c9Spaulson 				break;
37240e2b7c9Spaulson 			case '?':
37340e2b7c9Spaulson 			default :
37440e2b7c9Spaulson 				usage(func);
37540e2b7c9Spaulson 			}
37640e2b7c9Spaulson 		}
37740e2b7c9Spaulson 
37840e2b7c9Spaulson 		/*
37940e2b7c9Spaulson 		 * allocate(1) must be supplied with one device argument
38040e2b7c9Spaulson 		 */
38140e2b7c9Spaulson 		if ((argc - optind) != 1) {
38240e2b7c9Spaulson 			usage(func);
38340e2b7c9Spaulson 		} else {
38440e2b7c9Spaulson 			device = argv[optind];
38540e2b7c9Spaulson 		}
38640e2b7c9Spaulson 	}
38740e2b7c9Spaulson 
38840e2b7c9Spaulson 	else if (func == 1) {	/* deallocate */
389*45916cd2Sjpk 		while ((c = getopt(argc, argv, "gswz:FI")) != -1) {
39040e2b7c9Spaulson 			switch (c) {
391*45916cd2Sjpk 			case 'g':
392*45916cd2Sjpk 				if (system_labeled)
393*45916cd2Sjpk 					optflg |= TYPE;
394*45916cd2Sjpk 				else
395*45916cd2Sjpk 					usage(func);
396*45916cd2Sjpk 				break;
39740e2b7c9Spaulson 			case 's':
39840e2b7c9Spaulson 				optflg |= SILENT;
39940e2b7c9Spaulson 				break;
400*45916cd2Sjpk 			case 'w':
401*45916cd2Sjpk 				if (system_labeled) {
402*45916cd2Sjpk 					optflg |= WINDOWING;
403*45916cd2Sjpk 					windowing = 1;
404*45916cd2Sjpk 				} else {
405*45916cd2Sjpk 					usage(func);
406*45916cd2Sjpk 				}
407*45916cd2Sjpk 				break;
408*45916cd2Sjpk 			case 'z':
409*45916cd2Sjpk 				if (system_labeled) {
410*45916cd2Sjpk 					optflg |= ZONENAME;
411*45916cd2Sjpk 					zonename = optarg;
412*45916cd2Sjpk 				} else {
413*45916cd2Sjpk 					usage(func);
414*45916cd2Sjpk 				}
415*45916cd2Sjpk 				break;
41640e2b7c9Spaulson 			case 'F':
41740e2b7c9Spaulson 				optflg |= FORCE;
41840e2b7c9Spaulson 				break;
41940e2b7c9Spaulson 			case 'I':
42040e2b7c9Spaulson 				optflg |= FORCE_ALL;
42140e2b7c9Spaulson 				break;
42240e2b7c9Spaulson 			case '?':
42340e2b7c9Spaulson 			default :
42440e2b7c9Spaulson 				usage(func);
42540e2b7c9Spaulson 			}
42640e2b7c9Spaulson 		}
42740e2b7c9Spaulson 
42840e2b7c9Spaulson 		if ((optflg & FORCE) && (optflg & FORCE_ALL))
42940e2b7c9Spaulson 			usage(func);
43040e2b7c9Spaulson 
431*45916cd2Sjpk 		if (system_labeled && ((optflg & FORCE_ALL) && (optflg & TYPE)))
432*45916cd2Sjpk 			usage(func);
433*45916cd2Sjpk 
43440e2b7c9Spaulson 		/*
43540e2b7c9Spaulson 		 * deallocate(1) must be supplied with one device
43640e2b7c9Spaulson 		 * argument unless the '-I' argument is supplied
43740e2b7c9Spaulson 		 */
43840e2b7c9Spaulson 		if (!(optflg & FORCE_ALL)) {
43940e2b7c9Spaulson 			if ((argc - optind) != 1) {
44040e2b7c9Spaulson 				usage(func);
44140e2b7c9Spaulson 			} else {
44240e2b7c9Spaulson 				device = argv[optind];
44340e2b7c9Spaulson 			}
44440e2b7c9Spaulson 		} else {
44540e2b7c9Spaulson 			if ((argc - optind) >= 1) {
44640e2b7c9Spaulson 				usage(func);
44740e2b7c9Spaulson 			}
44840e2b7c9Spaulson 		}
44940e2b7c9Spaulson 	}
45040e2b7c9Spaulson 
45140e2b7c9Spaulson 	else if (func == 2) {	/* list_devices */
452*45916cd2Sjpk 		while ((c = getopt(argc, argv, "adlnsuwz:U:")) != -1) {
4537c478bd9Sstevel@tonic-gate 			switch (c) {
454*45916cd2Sjpk 			case 'a':
455*45916cd2Sjpk 				if (system_labeled) {
456*45916cd2Sjpk 					/*
457*45916cd2Sjpk 					 * list auths, cleaning programs,
458*45916cd2Sjpk 					 * labels.
459*45916cd2Sjpk 					 */
460*45916cd2Sjpk 					optflg |= LISTATTRS;
461*45916cd2Sjpk 				} else {
462*45916cd2Sjpk 					usage(func);
463*45916cd2Sjpk 				}
464*45916cd2Sjpk 				break;
465*45916cd2Sjpk 			case 'd':
466*45916cd2Sjpk 				if (system_labeled) {
467*45916cd2Sjpk 					/*
468*45916cd2Sjpk 					 * list devalloc_defaults
469*45916cd2Sjpk 					 */
470*45916cd2Sjpk 					optflg |= LISTDEFS;
471*45916cd2Sjpk 				} else {
472*45916cd2Sjpk 					usage(func);
473*45916cd2Sjpk 				}
474*45916cd2Sjpk 				break;
475*45916cd2Sjpk 			case 'l':
476*45916cd2Sjpk 				optflg |= LISTALL;
477*45916cd2Sjpk 				break;
478*45916cd2Sjpk 			case 'n':
479*45916cd2Sjpk 				optflg |= LISTFREE;
480*45916cd2Sjpk 				break;
4817c478bd9Sstevel@tonic-gate 			case 's':
4827c478bd9Sstevel@tonic-gate 				optflg |= SILENT;
4837c478bd9Sstevel@tonic-gate 				break;
484*45916cd2Sjpk 			case 'u':
485*45916cd2Sjpk 				optflg |= LISTALLOC;
486*45916cd2Sjpk 				break;
487*45916cd2Sjpk 			case 'w':
488*45916cd2Sjpk 				if (system_labeled) {
489*45916cd2Sjpk 					/*
490*45916cd2Sjpk 					 * Private interface for use by
491*45916cd2Sjpk 					 * list_devices GUI
492*45916cd2Sjpk 					 */
493*45916cd2Sjpk 					optflg |= WINDOWING;
494*45916cd2Sjpk 				} else {
495*45916cd2Sjpk 					usage(func);
496*45916cd2Sjpk 				}
497*45916cd2Sjpk 				break;
498*45916cd2Sjpk 			case 'z':
499*45916cd2Sjpk 				if (system_labeled) {
500*45916cd2Sjpk 					optflg |= ZONENAME;
501*45916cd2Sjpk 					zonename = optarg;
502*45916cd2Sjpk 				} else {
503*45916cd2Sjpk 					usage(func);
504*45916cd2Sjpk 				}
505*45916cd2Sjpk 				break;
5067c478bd9Sstevel@tonic-gate 			case 'U':
5077c478bd9Sstevel@tonic-gate 				optflg |= USERID;
50840e2b7c9Spaulson 				uid = atoi(optarg);
5097c478bd9Sstevel@tonic-gate 				break;
5107c478bd9Sstevel@tonic-gate 			case '?':
5117c478bd9Sstevel@tonic-gate 			default :
5127c478bd9Sstevel@tonic-gate 				usage(func);
51340e2b7c9Spaulson 			}
5147c478bd9Sstevel@tonic-gate 		}
5157c478bd9Sstevel@tonic-gate 
516*45916cd2Sjpk 		if (system_labeled) {
517*45916cd2Sjpk 			if (((optflg & LISTALL) && (optflg & LISTFREE)) ||
518*45916cd2Sjpk 			    ((optflg & LISTALL) && (optflg & LISTALLOC)) ||
519*45916cd2Sjpk 			    ((optflg & LISTFREE) && (optflg & LISTALLOC)) ||
520*45916cd2Sjpk 			    ((optflg & LISTDEFS) &&
521*45916cd2Sjpk 			    (optflg & (LISTATTRS | LISTALL | LISTFREE |
522*45916cd2Sjpk 			    LISTALLOC | USERID | WINDOWING | ZONENAME))) ||
523*45916cd2Sjpk 			    (!(optflg & (LISTALL | LISTFREE | LISTALLOC |
524*45916cd2Sjpk 			    LISTDEFS | WINDOWING))))
52540e2b7c9Spaulson 				usage(func);
526*45916cd2Sjpk 		} else if (((optflg & LISTALL) && (optflg & LISTFREE)) ||
527*45916cd2Sjpk 		    ((optflg & LISTALL) && (optflg & LISTALLOC)) ||
528*45916cd2Sjpk 		    ((optflg & LISTFREE) && (optflg & LISTALLOC)) ||
529*45916cd2Sjpk 		    (!(optflg & (LISTALL | LISTFREE | LISTALLOC)))) {
530*45916cd2Sjpk 			usage(func);
531*45916cd2Sjpk 		}
53240e2b7c9Spaulson 
53340e2b7c9Spaulson 		/*
53440e2b7c9Spaulson 		 * list_devices(1) takes an optional device argument
53540e2b7c9Spaulson 		 */
53640e2b7c9Spaulson 		if ((argc - optind) == 1) {
53740e2b7c9Spaulson 			device = argv[optind];
53840e2b7c9Spaulson 		} else {
53940e2b7c9Spaulson 			if ((argc - optind) > 1) {
54040e2b7c9Spaulson 				usage(func);
54140e2b7c9Spaulson 			}
54240e2b7c9Spaulson 		}
54340e2b7c9Spaulson 	}
54440e2b7c9Spaulson 
54540e2b7c9Spaulson 	if (optflg & USERNAME) {
546*45916cd2Sjpk 		if (getpwnam_r(uname, &pw_ent, pw_buf, sizeof (pw_buf)) ==
547*45916cd2Sjpk 		    NULL) {
548*45916cd2Sjpk 			(void) fprintf(stderr,
549*45916cd2Sjpk 			    gettext("Invalid user name -- %s -- \n"), uname);
55040e2b7c9Spaulson 			exit(1);
55140e2b7c9Spaulson 		}
552*45916cd2Sjpk 		uid = pw_ent.pw_uid;
553*45916cd2Sjpk 	} else if (optflg & USERID) {
554*45916cd2Sjpk 		if (getpwuid_r(uid, &pw_ent, pw_buf, sizeof (pw_buf)) == NULL) {
555*45916cd2Sjpk 			(void) fprintf(stderr,
556*45916cd2Sjpk 			    gettext("Invalid user ID -- %d -- \n"), uid);
55740e2b7c9Spaulson 			exit(1);
5587c478bd9Sstevel@tonic-gate 		}
559*45916cd2Sjpk 		uid = pw_ent.pw_uid;
560*45916cd2Sjpk 	} else {
561*45916cd2Sjpk 		/*
562*45916cd2Sjpk 		 * caller's uid is the default if no user specified.
563*45916cd2Sjpk 		 */
564*45916cd2Sjpk 		uid = getuid();
5657c478bd9Sstevel@tonic-gate 	}
5667c478bd9Sstevel@tonic-gate 
567*45916cd2Sjpk 	/*
568*45916cd2Sjpk 	 * global zone is the default if no zonename specified.
569*45916cd2Sjpk 	 */
570*45916cd2Sjpk 	if (zonename == NULL) {
571*45916cd2Sjpk 		zonename = zname;
572*45916cd2Sjpk 	} else {
573*45916cd2Sjpk 		if (zone_get_id(zonename, &zoneid) != 0) {
574*45916cd2Sjpk 			(void) fprintf(stderr,
575*45916cd2Sjpk 			    gettext("Invalid zone name -- %s -- \n"), zonename);
576*45916cd2Sjpk 			exit(1);
5777c478bd9Sstevel@tonic-gate 		}
578*45916cd2Sjpk 	}
579*45916cd2Sjpk 
580*45916cd2Sjpk 	if (func == 0)
581*45916cd2Sjpk 		error = allocate(optflg, uid, device, zonename);
582*45916cd2Sjpk 	else if (func == 1)
583*45916cd2Sjpk 		error = deallocate(optflg, uid, device, zonename);
584*45916cd2Sjpk 	else if (func == 2)
585*45916cd2Sjpk 		error = list_devices(optflg, uid, device, zonename);
58640e2b7c9Spaulson 
5877c478bd9Sstevel@tonic-gate 	(void) audit_allocate_record(error);
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 	if (error) {
5907c478bd9Sstevel@tonic-gate 		if (!(optflg & SILENT))
5917c478bd9Sstevel@tonic-gate 			print_error(error, name);
5927c478bd9Sstevel@tonic-gate 		exit(error);
5937c478bd9Sstevel@tonic-gate 	}
5947c478bd9Sstevel@tonic-gate 
5957c478bd9Sstevel@tonic-gate 	return (0);
5967c478bd9Sstevel@tonic-gate }
597*45916cd2Sjpk 
598*45916cd2Sjpk /*
599*45916cd2Sjpk  * Display error message via /etc/security/lib/wdwmsg script
600*45916cd2Sjpk  */
601*45916cd2Sjpk static int
602*45916cd2Sjpk wdwmsg(char *name, char *msg)
603*45916cd2Sjpk {
604*45916cd2Sjpk 	pid_t child_pid;
605*45916cd2Sjpk 	pid_t wait_pid;
606*45916cd2Sjpk 	int child_status;
607*45916cd2Sjpk 
608*45916cd2Sjpk 	/* Fork a child */
609*45916cd2Sjpk 	switch (child_pid = fork()) {
610*45916cd2Sjpk 	case -1:	/* FAILURE */
611*45916cd2Sjpk 		return (-1);
612*45916cd2Sjpk 		break;
613*45916cd2Sjpk 
614*45916cd2Sjpk 	case 0:		/* CHILD */
615*45916cd2Sjpk 		(void) execl("/etc/security/lib/wdwmsg", "wdwmsg", msg,
616*45916cd2Sjpk 		    name, "OK", NULL);
617*45916cd2Sjpk 		/* If exec failed, send message to stderr */
618*45916cd2Sjpk 		(void) fprintf(stderr, "%s", msg);
619*45916cd2Sjpk 		return (-1);
620*45916cd2Sjpk 
621*45916cd2Sjpk 	default:	/* PARENT */
622*45916cd2Sjpk 		/* Wait for child to exit */
623*45916cd2Sjpk 		wait_pid = waitpid(child_pid, &child_status, 0);
624*45916cd2Sjpk 		if ((wait_pid < 0) && (errno == ECHILD))
625*45916cd2Sjpk 			return (0);
626*45916cd2Sjpk 		if ((wait_pid < 0) || (wait_pid != child_pid))
627*45916cd2Sjpk 			return (-1);
628*45916cd2Sjpk 		if (WIFEXITED(child_status))
629*45916cd2Sjpk 			return (WEXITSTATUS(child_status));
630*45916cd2Sjpk 		if (WIFSIGNALED(child_status))
631*45916cd2Sjpk 			return (WTERMSIG(child_status));
632*45916cd2Sjpk 		return (0);
633*45916cd2Sjpk 	}
634*45916cd2Sjpk }
635