4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
38 #include <nss_dbdefs.h>
39 #include <sys/types.h>
43 #include <bsm/devalloc.h>
46 #if !defined(TEXT_DOMAIN)
47 #define TEXT_DOMAIN "SUNW_OST_OSCMD"
50 #define ALLOC "allocate"
51 #define DEALLOC "deallocate"
52 #define LIST "list_devices"
54 extern void audit_allocate_argv(int, int, char *[]);
55 extern int audit_allocate_record(int);
57 static int windowing
= 0;
58 static int wdwmsg(char *name
, char *msg
);
65 use
[0] = gettext("allocate "
66 "[-s] [-U uname] [-F] device|-g dev-type");
67 use
[1] = gettext("deallocate [-s] [-F] device|-c dev-class");
68 use
[2] = gettext("deallocate [-s] -I");
69 use
[3] = gettext("list_devices "
70 "[-s] [-U uid] -l|-n|-u [device]");
71 use
[4] = gettext("list_devices "
72 "[-s] [-U uid] [-l|-n|-u] -c dev-class");
76 (void) fprintf(stderr
, "%s\n", use
[0]);
79 (void) fprintf(stderr
, "%s\n%s\n",
83 (void) fprintf(stderr
, "%s\n%s\n",
87 (void) fprintf(stderr
, "%s\n%s\n%s\n%s\n%s\n",
88 use
[0], use
[1], use
[2], use
[3], use
[4]);
94 print_error(int error
, char *name
)
101 msg
= gettext("Specified device is allocated to another user.");
104 msg
= gettext("Failed to chown.");
107 msg
= gettext("Unable to clean up device.");
111 "Can't exec device-clean program for specified device.");
114 msg
= gettext("Can't force deallocate specified device.");
118 "Can't access DAC file for the device specified.");
122 "Device allocation feature is not activated "
126 msg
= gettext("Device not allocatable.");
129 msg
= gettext("No default attributes for specified "
133 msg
= gettext("Concurrent operations for specified device, "
137 msg
= gettext("Device name is too long.");
140 msg
= gettext("Device not allocated.");
143 msg
= gettext("Device name error.");
146 msg
= gettext("Device specified is in allocate error state.");
149 msg
= gettext("Can't find name of the zone to which "
150 "device is allocated.");
154 "Device special file(s) missing for specified device.");
156 case LOGINDEVPERMERR
:
157 msg
= gettext("Device controlled by logindevperm(4)");
160 msg
= gettext("No entry for specified device.");
163 msg
= gettext("No entry for specified device.");
166 msg
= gettext("Device already allocated.");
169 msg
= gettext("Failed to set ACL.");
173 "User lacks authorization required for this operation.");
176 msg
= gettext("Failed to configure device in zone.");
179 msg
= gettext("Unknown error code.");
184 (void) snprintf(msgbuf
, sizeof (msgbuf
), "%s: %s\n", name
, msg
);
185 (void) wdwmsg(name
, msgbuf
);
187 (void) fprintf(stderr
, "%s: %s\n", name
, msg
);
188 (void) fflush(stderr
);
192 char *newenv
[] = {"PATH=/usr/bin:/usr/sbin",
193 NULL
, /* for LC_ALL */
194 NULL
, /* for LC_COLLATE */
195 NULL
, /* for LC_CTYPE */
196 NULL
, /* for LC_MESSAGES */
197 NULL
, /* for LC_NUMERIC */
198 NULL
, /* for LC_TIME */
204 getenvent(char *name
, char *env
[])
206 for (; *env
!= NULL
; env
++) {
207 if (strncmp(*env
, name
, strlen(name
)) == 0)
214 main(int argc
, char *argv
[], char *envp
[])
217 int func
= -1, optflg
= 0, error
= 0, c
;
220 char *uname
= NULL
, *device
= NULL
, *zonename
= NULL
;
222 char pw_buf
[NSS_BUFLEN_PASSWD
];
223 struct passwd pw_ent
;
224 int env_num
= 1; /* PATH= is 0 entry */
229 (void) setlocale(LC_ALL
, "");
230 (void) textdomain(TEXT_DOMAIN
);
233 * get all enviroment variables
234 * which affect on internationalization.
236 env
= getenvent("LC_ALL=", envp
);
238 newenv
[env_num
++] = env
;
239 env
= getenvent("LC_COLLATE=", envp
);
241 newenv
[env_num
++] = env
;
242 env
= getenvent("LC_CTYPE=", envp
);
244 newenv
[env_num
++] = env
;
245 env
= getenvent("LC_MESSAGES=", envp
);
247 newenv
[env_num
++] = env
;
248 env
= getenvent("LC_NUMERIC=", envp
);
250 newenv
[env_num
++] = env
;
251 env
= getenvent("LC_TIME=", envp
);
253 newenv
[env_num
++] = env
;
254 env
= getenvent("LANG=", envp
);
256 newenv
[env_num
] = env
;
258 if ((name
= strrchr(argv
[0], '/')) == NULL
)
263 if (strcmp(name
, ALLOC
) == 0)
265 else if (strcmp(name
, DEALLOC
) == 0)
267 else if (strcmp(name
, LIST
) == 0)
272 audit_allocate_argv(func
, argc
, argv
);
274 if (func
== 0) { /* allocate */
275 while ((c
= getopt(argc
, argv
, "g:sFU:")) != -1) {
298 * allocate(1) must be supplied with one device argument
300 if (device
&& ((argc
- optind
) >= 1))
302 if (device
== NULL
) {
303 if ((argc
- optind
) != 1)
305 device
= argv
[optind
];
309 else if (func
== 1) { /* deallocate */
310 while ((c
= getopt(argc
, argv
, "c:sFI")) != -1) {
313 if (optflg
& (TYPE
| FORCE_ALL
))
322 if (optflg
& FORCE_ALL
)
327 if (optflg
& (CLASS
| TYPE
| FORCE
))
338 * deallocate(1) must be supplied with one device
339 * argument unless the '-I' argument is supplied
341 if (device
|| (optflg
& FORCE_ALL
)) {
342 if ((argc
- optind
) >= 1)
344 } else if (device
== NULL
) {
345 if ((argc
- optind
) != 1)
347 device
= argv
[optind
];
351 else if (func
== 2) { /* list_devices */
352 while ((c
= getopt(argc
, argv
, "c:lnsuU:")) != -1) {
359 if (optflg
& (LISTFREE
| LISTALLOC
| LISTDEFS
))
364 if (optflg
& (LISTALL
| LISTALLOC
| LISTDEFS
))
372 if (optflg
& (LISTALL
| LISTFREE
| LISTDEFS
))
377 if (optflg
& LISTDEFS
)
388 if (!(optflg
& (LISTALL
| LISTFREE
| LISTALLOC
))) {
389 if (!(optflg
& CLASS
))
394 * list_devices(1) takes an optional device argument.
396 if (device
&& ((argc
- optind
) >= 1))
398 if (device
== NULL
) {
399 if ((argc
- optind
) == 1)
400 device
= argv
[optind
];
401 else if ((argc
- optind
) > 1)
406 if (optflg
& USERNAME
) {
407 struct passwd
*result
;
408 getpwnam_r(uname
, &pw_ent
, pw_buf
, sizeof (pw_buf
), &result
);
410 (void) fprintf(stderr
,
411 gettext("Invalid user name -- %s -- \n"), uname
);
415 } else if (optflg
& USERID
) {
416 struct passwd
*result
;
417 getpwuid_r(uid
, &pw_ent
, pw_buf
, sizeof (pw_buf
), &result
);
419 (void) fprintf(stderr
,
420 gettext("Invalid user ID -- %d -- \n"), uid
);
426 * caller's uid is the default if no user specified.
432 * global zone is the default if no zonename specified.
434 if (zonename
== NULL
) {
437 if (zone_get_id(zonename
, &zoneid
) != 0) {
438 (void) fprintf(stderr
,
439 gettext("Invalid zone name -- %s -- \n"), zonename
);
445 error
= allocate(optflg
, uid
, device
, zonename
);
447 error
= deallocate(optflg
, uid
, device
, zonename
);
449 error
= list_devices(optflg
, uid
, device
, zonename
);
451 (void) audit_allocate_record(error
);
454 if (!(optflg
& SILENT
))
455 print_error(error
, name
);
463 * Display error message via /etc/security/lib/wdwmsg script
466 wdwmsg(char *name
, char *msg
)
473 switch (child_pid
= fork()) {
474 case -1: /* FAILURE */
479 (void) execl("/etc/security/lib/wdwmsg", "wdwmsg", msg
,
481 /* If exec failed, send message to stderr */
482 (void) fprintf(stderr
, "%s", msg
);
485 default: /* PARENT */
486 /* Wait for child to exit */
487 wait_pid
= waitpid(child_pid
, &child_status
, 0);
488 if ((wait_pid
< 0) && (errno
== ECHILD
))
490 if ((wait_pid
< 0) || (wait_pid
!= child_pid
))
492 if (WIFEXITED(child_status
))
493 return (WEXITSTATUS(child_status
));
494 if (WIFSIGNALED(child_status
))
495 return (WTERMSIG(child_status
));