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