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 (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright (c) 2001, 2010, Oracle and/or its affiliates. All rights reserved. 23 */ 24 25 /* 26 * poolbind - bind processes, tasks, and projects to pools, and query process 27 * pool bindings 28 */ 29 30 #include <libgen.h> 31 #include <pool.h> 32 #include <stdio.h> 33 #include <stdlib.h> 34 #include <string.h> 35 #include <strings.h> 36 #include <unistd.h> 37 38 #include <locale.h> 39 #include <libintl.h> 40 41 #include <sys/procset.h> 42 #include <sys/types.h> 43 #include <sys/stat.h> 44 #include <errno.h> 45 #include <project.h> 46 #include <zone.h> 47 48 #include "utils.h" 49 50 #ifndef TEXT_DOMAIN 51 #define TEXT_DOMAIN "SYS_TEST" 52 #endif 53 54 #define eFLAG 0x1 55 #define iFLAG 0x2 56 #define pFLAG 0x4 57 #define qFLAG 0x8 58 #define QFLAG 0x10 59 60 static const char OPTS[] = "Qei:p:q"; 61 static struct { 62 idtype_t idtype; 63 char *str; 64 } idtypes[] = { 65 { P_PID, "pid" }, 66 { P_TASKID, "taskid" }, 67 { P_PROJID, "projid" }, 68 { P_PROJID, "project" }, 69 { P_ZONEID, "zoneid" }, 70 { -1, NULL } 71 }; 72 73 int error = E_PO_SUCCESS; 74 75 void exec_cmd(char *, char *[]); 76 void process_ids(char *, uint_t, idtype_t, char *, int, char *[]); 77 78 void 79 usage(void) 80 { 81 (void) fprintf(stderr, 82 gettext("Usage:\n" 83 " poolbind -p pool_name -e command [arguments...]\n" 84 " poolbind -p pool_name " 85 "[-i pid | -i taskid | -i projid | -i zoneid] id ...\n" 86 " poolbind -q pid ...\n" 87 " poolbind -Q pid ... \n")); 88 exit(E_USAGE); 89 } 90 91 int 92 print_resource_binding(const char *type, pid_t pid) 93 { 94 char *resource_name; 95 96 if ((resource_name = pool_get_resource_binding(type, pid)) == NULL) 97 warn(gettext("getting '%s' binding for %d: %s\n"), type, 98 (int)pid, get_errstr()); 99 else 100 (void) printf("%d\t%s\t%s\n", (int)pid, type, resource_name); 101 free(resource_name); 102 return (PO_SUCCESS); 103 } 104 105 int 106 main(int argc, char *argv[]) 107 { 108 char c; 109 int i; 110 idtype_t idtype = P_PID; 111 char *idstr = "pid"; 112 char *pool_name = NULL; 113 uint_t flags = 0; 114 int status; 115 116 (void) getpname(argv[0]); 117 (void) setlocale(LC_ALL, ""); 118 (void) textdomain(TEXT_DOMAIN); 119 120 while ((c = getopt(argc, argv, OPTS)) != EOF) { 121 switch (c) { 122 case 'Q': 123 if (flags & (qFLAG | iFLAG | pFLAG)) 124 usage(); 125 flags |= QFLAG; 126 break; 127 case 'e': 128 if (flags & (iFLAG | qFLAG | QFLAG)) 129 usage(); 130 flags |= eFLAG; 131 break; 132 case 'i': 133 for (i = 0; idtypes[i].str != NULL; i++) { 134 if (strcmp(optarg, idtypes[i].str) == 0) { 135 idtype = idtypes[i].idtype; 136 idstr = idtypes[i].str; 137 break; 138 } 139 } 140 if ((flags & (iFLAG | qFLAG | QFLAG)) || 141 idtypes[i].str == NULL) 142 usage(); 143 flags |= iFLAG; 144 break; 145 case 'p': 146 if (flags & (pFLAG | qFLAG | QFLAG)) 147 usage(); 148 flags |= pFLAG; 149 pool_name = optarg; 150 break; 151 case 'q': 152 if (flags & (pFLAG | iFLAG | QFLAG)) 153 usage(); 154 flags |= qFLAG; 155 break; 156 case '?': 157 default: 158 usage(); 159 } 160 } 161 162 argc -= optind; 163 argv += optind; 164 165 if (flags & eFLAG && pool_name == NULL) 166 usage(); 167 if (argc < 1 || (flags & (pFLAG | qFLAG | QFLAG)) == 0) 168 usage(); 169 170 /* 171 * Check to see that the pools facility is enabled 172 */ 173 if (pool_get_status(&status) != PO_SUCCESS) 174 die((ERR_OPEN_DYNAMIC), get_errstr()); 175 if (status == POOL_DISABLED) 176 die((ERR_OPEN_DYNAMIC), strerror(ENOTACTIVE)); 177 178 if (flags & eFLAG) 179 exec_cmd(pool_name, argv); 180 /*NOTREACHED*/ 181 else 182 process_ids(pool_name, flags, idtype, idstr, argc, argv); 183 184 return (error); 185 } 186 187 void 188 exec_cmd(char *pool_name, char *argv[]) 189 { 190 if (pool_set_binding(pool_name, P_PID, getpid()) != PO_SUCCESS) { 191 warn(gettext("binding to pool '%s': %s\n"), pool_name, 192 get_errstr()); 193 error = E_ERROR; 194 return; 195 } 196 197 if (execvp(argv[0], argv) == -1) 198 die(gettext("exec of %s failed"), argv[0]); 199 /*NOTREACHED*/ 200 } 201 202 void 203 process_ids(char *pool_name, uint_t flags, idtype_t idtype, char *idstr, 204 int argc, char *argv[]) 205 { 206 int i; 207 id_t id; 208 209 for (i = 0; i < argc; i++) { 210 char *endp; 211 char *poolname; 212 213 errno = 0; 214 id = (id_t)strtol(argv[i], &endp, 10); 215 if (errno != 0 || 216 (endp && endp != argv[i] + strlen(argv[i])) || 217 (idtype == P_ZONEID && 218 getzonenamebyid(id, NULL, 0) == -1)) { 219 /* 220 * The string does not completely parse to 221 * an integer, or it represents an invalid 222 * zone id. 223 */ 224 225 /* 226 * It must be a project or zone name. 227 */ 228 if (idtype == P_ZONEID) { 229 if (zone_get_id(argv[i], &id) != 0) { 230 warn(gettext("invalid zone '%s'\n"), 231 argv[i]); 232 error = E_ERROR; 233 continue; 234 } 235 /* make sure the zone is booted */ 236 if (id == -1) { 237 warn(gettext("zone '%s' is not " 238 "active\n"), argv[i]); 239 error = E_ERROR; 240 continue; 241 } 242 } else if (idtype == P_PROJID) { 243 if ((id = getprojidbyname(argv[i])) < 0) { 244 warn(gettext("failed to get project " 245 "id for project: '%s'"), argv[i]); 246 error = E_ERROR; 247 continue; 248 } 249 } else { 250 warn(gettext("invalid %s '%s'\n"), 251 idstr, argv[i]); 252 error = E_ERROR; 253 continue; 254 } 255 } 256 257 if (flags & pFLAG) { 258 if (pool_set_binding(pool_name, idtype, id) != 259 PO_SUCCESS) { 260 warn(gettext("binding %s %ld to pool '%s': " 261 "%s\n"), idstr, id, pool_name, 262 get_errstr()); 263 error = E_ERROR; 264 } 265 continue; 266 } 267 268 if (flags & qFLAG) { 269 if ((poolname = pool_get_binding(id)) == NULL) { 270 warn(gettext("couldn't determine binding for " 271 "pid %ld: %s\n"), id, get_errstr()); 272 error = E_ERROR; 273 } else { 274 (void) printf("%ld\t%s\n", id, poolname); 275 free(poolname); 276 } 277 } 278 if (flags & QFLAG) { 279 uint_t j, count; 280 const char **resource_types; 281 (void) pool_resource_type_list(NULL, &count); 282 283 if ((resource_types = malloc(count * 284 sizeof (const char *))) == NULL) { 285 warn(gettext("couldn't allocate query memory " 286 "for pid %ld: %s\n"), id, get_errstr()); 287 error = E_ERROR; 288 } 289 (void) pool_resource_type_list(resource_types, &count); 290 291 for (j = 0; j < count; j++) 292 (void) print_resource_binding(resource_types[j], 293 (pid_t)id); 294 free(resource_types); 295 } 296 } 297 } 298