10Sstevel@tonic-gate /*
20Sstevel@tonic-gate * CDDL HEADER START
30Sstevel@tonic-gate *
40Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5*12086SGangadhar.M@Sun.COM * Common Development and Distribution License (the "License").
6*12086SGangadhar.M@Sun.COM * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate *
80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate * See the License for the specific language governing permissions
110Sstevel@tonic-gate * and limitations under the License.
120Sstevel@tonic-gate *
130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate *
190Sstevel@tonic-gate * CDDL HEADER END
200Sstevel@tonic-gate */
210Sstevel@tonic-gate /*
22*12086SGangadhar.M@Sun.COM * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate */
240Sstevel@tonic-gate
250Sstevel@tonic-gate /*
260Sstevel@tonic-gate * poolbind - bind processes, tasks, and projects to pools, and query process
270Sstevel@tonic-gate * pool bindings
280Sstevel@tonic-gate */
290Sstevel@tonic-gate
300Sstevel@tonic-gate #include <libgen.h>
310Sstevel@tonic-gate #include <pool.h>
320Sstevel@tonic-gate #include <stdio.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <string.h>
350Sstevel@tonic-gate #include <strings.h>
360Sstevel@tonic-gate #include <unistd.h>
370Sstevel@tonic-gate
380Sstevel@tonic-gate #include <locale.h>
390Sstevel@tonic-gate #include <libintl.h>
400Sstevel@tonic-gate
410Sstevel@tonic-gate #include <sys/procset.h>
420Sstevel@tonic-gate #include <sys/types.h>
430Sstevel@tonic-gate #include <sys/stat.h>
440Sstevel@tonic-gate #include <errno.h>
450Sstevel@tonic-gate #include <project.h>
460Sstevel@tonic-gate #include <zone.h>
470Sstevel@tonic-gate
480Sstevel@tonic-gate #include "utils.h"
490Sstevel@tonic-gate
500Sstevel@tonic-gate #ifndef TEXT_DOMAIN
510Sstevel@tonic-gate #define TEXT_DOMAIN "SYS_TEST"
520Sstevel@tonic-gate #endif
530Sstevel@tonic-gate
540Sstevel@tonic-gate #define eFLAG 0x1
550Sstevel@tonic-gate #define iFLAG 0x2
560Sstevel@tonic-gate #define pFLAG 0x4
570Sstevel@tonic-gate #define qFLAG 0x8
580Sstevel@tonic-gate #define QFLAG 0x10
590Sstevel@tonic-gate
600Sstevel@tonic-gate static const char OPTS[] = "Qei:p:q";
610Sstevel@tonic-gate static struct {
620Sstevel@tonic-gate idtype_t idtype;
630Sstevel@tonic-gate char *str;
640Sstevel@tonic-gate } idtypes[] = {
650Sstevel@tonic-gate { P_PID, "pid" },
660Sstevel@tonic-gate { P_TASKID, "taskid" },
670Sstevel@tonic-gate { P_PROJID, "projid" },
680Sstevel@tonic-gate { P_PROJID, "project" },
690Sstevel@tonic-gate { P_ZONEID, "zoneid" },
700Sstevel@tonic-gate { -1, NULL }
710Sstevel@tonic-gate };
720Sstevel@tonic-gate
730Sstevel@tonic-gate int error = E_PO_SUCCESS;
740Sstevel@tonic-gate
750Sstevel@tonic-gate void exec_cmd(char *, char *[]);
760Sstevel@tonic-gate void process_ids(char *, uint_t, idtype_t, char *, int, char *[]);
770Sstevel@tonic-gate
780Sstevel@tonic-gate void
usage(void)790Sstevel@tonic-gate usage(void)
800Sstevel@tonic-gate {
810Sstevel@tonic-gate (void) fprintf(stderr,
820Sstevel@tonic-gate gettext("Usage:\n"
830Sstevel@tonic-gate " poolbind -p pool_name -e command [arguments...]\n"
840Sstevel@tonic-gate " poolbind -p pool_name "
850Sstevel@tonic-gate "[-i pid | -i taskid | -i projid | -i zoneid] id ...\n"
860Sstevel@tonic-gate " poolbind -q pid ...\n"
870Sstevel@tonic-gate " poolbind -Q pid ... \n"));
880Sstevel@tonic-gate exit(E_USAGE);
890Sstevel@tonic-gate }
900Sstevel@tonic-gate
910Sstevel@tonic-gate int
print_resource_binding(const char * type,pid_t pid)920Sstevel@tonic-gate print_resource_binding(const char *type, pid_t pid)
930Sstevel@tonic-gate {
940Sstevel@tonic-gate char *resource_name;
950Sstevel@tonic-gate
960Sstevel@tonic-gate if ((resource_name = pool_get_resource_binding(type, pid)) == NULL)
970Sstevel@tonic-gate warn(gettext("getting '%s' binding for %d: %s\n"), type,
980Sstevel@tonic-gate (int)pid, get_errstr());
990Sstevel@tonic-gate else
1000Sstevel@tonic-gate (void) printf("%d\t%s\t%s\n", (int)pid, type, resource_name);
1010Sstevel@tonic-gate free(resource_name);
1020Sstevel@tonic-gate return (PO_SUCCESS);
1030Sstevel@tonic-gate }
1040Sstevel@tonic-gate
1050Sstevel@tonic-gate int
main(int argc,char * argv[])1060Sstevel@tonic-gate main(int argc, char *argv[])
1070Sstevel@tonic-gate {
1080Sstevel@tonic-gate char c;
1090Sstevel@tonic-gate int i;
1100Sstevel@tonic-gate idtype_t idtype = P_PID;
1110Sstevel@tonic-gate char *idstr = "pid";
1120Sstevel@tonic-gate char *pool_name = NULL;
1130Sstevel@tonic-gate uint_t flags = 0;
1140Sstevel@tonic-gate int status;
1150Sstevel@tonic-gate
1160Sstevel@tonic-gate (void) getpname(argv[0]);
1170Sstevel@tonic-gate (void) setlocale(LC_ALL, "");
1180Sstevel@tonic-gate (void) textdomain(TEXT_DOMAIN);
1190Sstevel@tonic-gate
1200Sstevel@tonic-gate while ((c = getopt(argc, argv, OPTS)) != EOF) {
1210Sstevel@tonic-gate switch (c) {
1220Sstevel@tonic-gate case 'Q':
1230Sstevel@tonic-gate if (flags & (qFLAG | iFLAG | pFLAG))
1240Sstevel@tonic-gate usage();
1250Sstevel@tonic-gate flags |= QFLAG;
1260Sstevel@tonic-gate break;
1270Sstevel@tonic-gate case 'e':
1280Sstevel@tonic-gate if (flags & (iFLAG | qFLAG | QFLAG))
1290Sstevel@tonic-gate usage();
1300Sstevel@tonic-gate flags |= eFLAG;
1310Sstevel@tonic-gate break;
1320Sstevel@tonic-gate case 'i':
1330Sstevel@tonic-gate for (i = 0; idtypes[i].str != NULL; i++) {
1340Sstevel@tonic-gate if (strcmp(optarg, idtypes[i].str) == 0) {
1350Sstevel@tonic-gate idtype = idtypes[i].idtype;
1360Sstevel@tonic-gate idstr = idtypes[i].str;
1370Sstevel@tonic-gate break;
1380Sstevel@tonic-gate }
1390Sstevel@tonic-gate }
1400Sstevel@tonic-gate if ((flags & (iFLAG | qFLAG | QFLAG)) ||
1410Sstevel@tonic-gate idtypes[i].str == NULL)
1420Sstevel@tonic-gate usage();
1430Sstevel@tonic-gate flags |= iFLAG;
1440Sstevel@tonic-gate break;
1450Sstevel@tonic-gate case 'p':
1460Sstevel@tonic-gate if (flags & (pFLAG | qFLAG | QFLAG))
1470Sstevel@tonic-gate usage();
1480Sstevel@tonic-gate flags |= pFLAG;
1490Sstevel@tonic-gate pool_name = optarg;
1500Sstevel@tonic-gate break;
1510Sstevel@tonic-gate case 'q':
1520Sstevel@tonic-gate if (flags & (pFLAG | iFLAG | QFLAG))
1530Sstevel@tonic-gate usage();
1540Sstevel@tonic-gate flags |= qFLAG;
1550Sstevel@tonic-gate break;
1560Sstevel@tonic-gate case '?':
1570Sstevel@tonic-gate default:
1580Sstevel@tonic-gate usage();
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate }
1610Sstevel@tonic-gate
1620Sstevel@tonic-gate argc -= optind;
1630Sstevel@tonic-gate argv += optind;
1640Sstevel@tonic-gate
1650Sstevel@tonic-gate if (flags & eFLAG && pool_name == NULL)
1660Sstevel@tonic-gate usage();
1670Sstevel@tonic-gate if (argc < 1 || (flags & (pFLAG | qFLAG | QFLAG)) == 0)
1680Sstevel@tonic-gate usage();
1690Sstevel@tonic-gate
1700Sstevel@tonic-gate /*
1710Sstevel@tonic-gate * Check to see that the pools facility is enabled
1720Sstevel@tonic-gate */
1730Sstevel@tonic-gate if (pool_get_status(&status) != PO_SUCCESS)
1740Sstevel@tonic-gate die((ERR_OPEN_DYNAMIC), get_errstr());
1750Sstevel@tonic-gate if (status == POOL_DISABLED)
1760Sstevel@tonic-gate die((ERR_OPEN_DYNAMIC), strerror(ENOTACTIVE));
1770Sstevel@tonic-gate
1780Sstevel@tonic-gate if (flags & eFLAG)
1790Sstevel@tonic-gate exec_cmd(pool_name, argv);
1800Sstevel@tonic-gate /*NOTREACHED*/
1810Sstevel@tonic-gate else
1820Sstevel@tonic-gate process_ids(pool_name, flags, idtype, idstr, argc, argv);
1830Sstevel@tonic-gate
1840Sstevel@tonic-gate return (error);
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate
1870Sstevel@tonic-gate void
exec_cmd(char * pool_name,char * argv[])1880Sstevel@tonic-gate exec_cmd(char *pool_name, char *argv[])
1890Sstevel@tonic-gate {
1900Sstevel@tonic-gate if (pool_set_binding(pool_name, P_PID, getpid()) != PO_SUCCESS) {
1910Sstevel@tonic-gate warn(gettext("binding to pool '%s': %s\n"), pool_name,
1920Sstevel@tonic-gate get_errstr());
1930Sstevel@tonic-gate error = E_ERROR;
1940Sstevel@tonic-gate return;
1950Sstevel@tonic-gate }
1960Sstevel@tonic-gate
197*12086SGangadhar.M@Sun.COM if (execvp(argv[0], argv) == -1)
1980Sstevel@tonic-gate die(gettext("exec of %s failed"), argv[0]);
1990Sstevel@tonic-gate /*NOTREACHED*/
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate
2020Sstevel@tonic-gate void
process_ids(char * pool_name,uint_t flags,idtype_t idtype,char * idstr,int argc,char * argv[])2030Sstevel@tonic-gate process_ids(char *pool_name, uint_t flags, idtype_t idtype, char *idstr,
2040Sstevel@tonic-gate int argc, char *argv[])
2050Sstevel@tonic-gate {
2060Sstevel@tonic-gate int i;
2070Sstevel@tonic-gate id_t id;
2080Sstevel@tonic-gate
2090Sstevel@tonic-gate for (i = 0; i < argc; i++) {
2100Sstevel@tonic-gate char *endp;
2110Sstevel@tonic-gate char *poolname;
2120Sstevel@tonic-gate
2130Sstevel@tonic-gate errno = 0;
2140Sstevel@tonic-gate id = (id_t)strtol(argv[i], &endp, 10);
2150Sstevel@tonic-gate if (errno != 0 ||
2160Sstevel@tonic-gate (endp && endp != argv[i] + strlen(argv[i])) ||
2170Sstevel@tonic-gate (idtype == P_ZONEID &&
2180Sstevel@tonic-gate getzonenamebyid(id, NULL, 0) == -1)) {
2190Sstevel@tonic-gate /*
2200Sstevel@tonic-gate * The string does not completely parse to
2210Sstevel@tonic-gate * an integer, or it represents an invalid
2220Sstevel@tonic-gate * zone id.
2230Sstevel@tonic-gate */
2240Sstevel@tonic-gate
2250Sstevel@tonic-gate /*
2260Sstevel@tonic-gate * It must be a project or zone name.
2270Sstevel@tonic-gate */
2280Sstevel@tonic-gate if (idtype == P_ZONEID) {
2290Sstevel@tonic-gate if (zone_get_id(argv[i], &id) != 0) {
2300Sstevel@tonic-gate warn(gettext("invalid zone '%s'\n"),
2310Sstevel@tonic-gate argv[i]);
2320Sstevel@tonic-gate error = E_ERROR;
2330Sstevel@tonic-gate continue;
2340Sstevel@tonic-gate }
2350Sstevel@tonic-gate /* make sure the zone is booted */
2360Sstevel@tonic-gate if (id == -1) {
2370Sstevel@tonic-gate warn(gettext("zone '%s' is not "
2380Sstevel@tonic-gate "active\n"), argv[i]);
2390Sstevel@tonic-gate error = E_ERROR;
2400Sstevel@tonic-gate continue;
2410Sstevel@tonic-gate }
2420Sstevel@tonic-gate } else if (idtype == P_PROJID) {
2430Sstevel@tonic-gate if ((id = getprojidbyname(argv[i])) < 0) {
2440Sstevel@tonic-gate warn(gettext("failed to get project "
2450Sstevel@tonic-gate "id for project: '%s'"), argv[i]);
2460Sstevel@tonic-gate error = E_ERROR;
2470Sstevel@tonic-gate continue;
2480Sstevel@tonic-gate }
2490Sstevel@tonic-gate } else {
2500Sstevel@tonic-gate warn(gettext("invalid %s '%s'\n"),
2510Sstevel@tonic-gate idstr, argv[i]);
2520Sstevel@tonic-gate error = E_ERROR;
2530Sstevel@tonic-gate continue;
2540Sstevel@tonic-gate }
2550Sstevel@tonic-gate }
2560Sstevel@tonic-gate
2570Sstevel@tonic-gate if (flags & pFLAG) {
2580Sstevel@tonic-gate if (pool_set_binding(pool_name, idtype, id) !=
2590Sstevel@tonic-gate PO_SUCCESS) {
2600Sstevel@tonic-gate warn(gettext("binding %s %ld to pool '%s': "
2610Sstevel@tonic-gate "%s\n"), idstr, id, pool_name,
2620Sstevel@tonic-gate get_errstr());
2630Sstevel@tonic-gate error = E_ERROR;
2640Sstevel@tonic-gate }
2650Sstevel@tonic-gate continue;
2660Sstevel@tonic-gate }
2670Sstevel@tonic-gate
2680Sstevel@tonic-gate if (flags & qFLAG) {
2690Sstevel@tonic-gate if ((poolname = pool_get_binding(id)) == NULL) {
2700Sstevel@tonic-gate warn(gettext("couldn't determine binding for "
2710Sstevel@tonic-gate "pid %ld: %s\n"), id, get_errstr());
2720Sstevel@tonic-gate error = E_ERROR;
2730Sstevel@tonic-gate } else {
2740Sstevel@tonic-gate (void) printf("%ld\t%s\n", id, poolname);
2750Sstevel@tonic-gate free(poolname);
2760Sstevel@tonic-gate }
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate if (flags & QFLAG) {
2790Sstevel@tonic-gate uint_t j, count;
2800Sstevel@tonic-gate const char **resource_types;
2810Sstevel@tonic-gate (void) pool_resource_type_list(NULL, &count);
2820Sstevel@tonic-gate
2830Sstevel@tonic-gate if ((resource_types = malloc(count *
2840Sstevel@tonic-gate sizeof (const char *))) == NULL) {
2850Sstevel@tonic-gate warn(gettext("couldn't allocate query memory "
2860Sstevel@tonic-gate "for pid %ld: %s\n"), id, get_errstr());
2870Sstevel@tonic-gate error = E_ERROR;
2880Sstevel@tonic-gate }
2890Sstevel@tonic-gate (void) pool_resource_type_list(resource_types, &count);
2900Sstevel@tonic-gate
2910Sstevel@tonic-gate for (j = 0; j < count; j++)
2920Sstevel@tonic-gate (void) print_resource_binding(resource_types[j],
2930Sstevel@tonic-gate (pid_t)id);
2940Sstevel@tonic-gate free(resource_types);
2950Sstevel@tonic-gate }
2960Sstevel@tonic-gate }
2970Sstevel@tonic-gate }
298