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 2009 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * Portions Copyright 2009 Chad Mynhier 26 */ 27 28 #include <procfs.h> 29 #include <unistd.h> 30 #include <stdlib.h> 31 #include <pwd.h> 32 #include <ctype.h> 33 #include <string.h> 34 #include <libintl.h> 35 #include <errno.h> 36 #include <zone.h> 37 #include <libzonecfg.h> 38 39 #include "prstat.h" 40 #include "prutil.h" 41 #include "prtable.h" 42 43 static plwp_t *plwp_tbl[PLWP_TBL_SZ]; 44 45 void 46 lwpid_init() 47 { 48 (void) memset(&plwp_tbl, 0, sizeof (plwp_t *) * PLWP_TBL_SZ); 49 } 50 51 static uid_t 52 pwd_getid(char *name) 53 { 54 struct passwd *pwd; 55 56 if ((pwd = getpwnam(name)) == NULL) 57 Die(gettext("invalid user name: %s\n"), name); 58 return (pwd->pw_uid); 59 } 60 61 void 62 pwd_getname(uid_t uid, char *name, int length, int noresolve) 63 { 64 struct passwd *pwd; 65 66 if (noresolve || (pwd = getpwuid(uid)) == NULL) { 67 (void) snprintf(name, length, "%u", uid); 68 } else { 69 (void) snprintf(name, length, "%s", pwd->pw_name); 70 } 71 } 72 73 void 74 add_uid(uidtbl_t *tbl, char *name) 75 { 76 uid_t *uid; 77 78 if (tbl->n_size == tbl->n_nent) { /* reallocation */ 79 if ((tbl->n_size *= 2) == 0) 80 tbl->n_size = 4; /* first time */ 81 tbl->n_list = Realloc(tbl->n_list, tbl->n_size*sizeof (uid_t)); 82 } 83 84 uid = &tbl->n_list[tbl->n_nent++]; 85 86 if (isdigit(name[0])) { 87 *uid = Atoi(name); 88 } else { 89 *uid = pwd_getid(name); 90 } 91 } 92 93 int 94 has_uid(uidtbl_t *tbl, uid_t uid) 95 { 96 size_t i; 97 98 if (tbl->n_nent) { /* do linear search if table is not empty */ 99 for (i = 0; i < tbl->n_nent; i++) 100 if (tbl->n_list[i] == uid) 101 return (1); 102 } else { 103 return (1); /* if table is empty return true */ 104 } 105 106 return (0); /* nothing has been found */ 107 } 108 109 void 110 add_element(table_t *table, long element) 111 { 112 if (table->t_size == table->t_nent) { 113 if ((table->t_size *= 2) == 0) 114 table->t_size = 4; 115 table->t_list = Realloc(table->t_list, 116 table->t_size * sizeof (long)); 117 } 118 table->t_list[table->t_nent++] = element; 119 } 120 121 int 122 has_element(table_t *table, long element) 123 { 124 size_t i; 125 126 if (table->t_nent) { /* do linear search if table is not empty */ 127 for (i = 0; i < table->t_nent; i++) 128 if (table->t_list[i] == element) 129 return (1); 130 } else { /* if table is empty then */ 131 return (1); /* pretend that element was found */ 132 } 133 134 return (0); /* element was not found */ 135 } 136 137 int 138 foreach_element(table_t *table, void *buf, void (*walker)(long, void *)) 139 { 140 size_t i; 141 142 if (table->t_nent) { 143 for (i = 0; i < table->t_nent; i++) 144 walker(table->t_list[i], buf); 145 } else { 146 return (0); 147 } 148 return (1); 149 } 150 151 void 152 add_zone(zonetbl_t *tbl, char *str) 153 { 154 zonename_t *entp; 155 zoneid_t id; 156 char *cp; 157 158 /* 159 * str should be either the name of a configured zone, or the 160 * id of a running zone. If str is a zone name, store the name 161 * in the table; otherwise, just store the id. 162 */ 163 if (zone_get_id(str, &id) != 0) { 164 Die(gettext("unknown zone -- %s\n"), str); 165 /*NOTREACHED*/ 166 } 167 168 /* was zone specified by name or id? */ 169 errno = 0; 170 if (id == (zoneid_t)strtol(str, &cp, 0) && errno == 0 && cp != str && 171 *cp == '\0') { 172 /* found it by id, don't store the name */ 173 str = NULL; 174 } 175 176 if (tbl->z_size == tbl->z_nent) { /* reallocation */ 177 if ((tbl->z_size *= 2) == 0) 178 tbl->z_size = 4; /* first time */ 179 tbl->z_list = 180 Realloc(tbl->z_list, tbl->z_size * sizeof (zonename_t)); 181 } 182 183 entp = &tbl->z_list[tbl->z_nent++]; 184 if (str) 185 (void) strlcpy(entp->z_name, str, ZONENAME_MAX); 186 else 187 entp->z_name[0] = '\0'; 188 entp->z_id = id; 189 } 190 191 int 192 has_zone(zonetbl_t *tbl, zoneid_t id) 193 { 194 long i; 195 196 if (tbl->z_nent) { /* do linear search if table is not empty */ 197 for (i = 0; i < tbl->z_nent; i++) 198 if (tbl->z_list[i].z_id == id) 199 return (1); 200 return (0); /* nothing has been found */ 201 } 202 203 return (1); /* if table is empty return true */ 204 } 205 206 /* 207 * Lookup ids for each zone name; this is done once each time /proc 208 * is scanned to avoid calling getzoneidbyname for each process. 209 */ 210 void 211 convert_zone(zonetbl_t *tbl) 212 { 213 long i; 214 zoneid_t id; 215 char *name; 216 217 for (i = 0; i < tbl->z_nent; i++) { 218 name = tbl->z_list[i].z_name; 219 if (name != NULL) { 220 if ((id = getzoneidbyname(name)) != -1) 221 tbl->z_list[i].z_id = id; 222 } 223 } 224 } 225 226 void 227 lwpid_add(lwp_info_t *lwp, pid_t pid, id_t lwpid) 228 { 229 plwp_t *elm = Zalloc(sizeof (plwp_t)); 230 int hash = pid % PLWP_TBL_SZ; 231 232 elm->l_pid = pid; 233 elm->l_lwpid = lwpid; 234 elm->l_lwp = lwp; 235 elm->l_next = plwp_tbl[hash]; /* add in front of chain */ 236 plwp_tbl[hash] = elm; 237 } 238 239 void 240 lwpid_del(pid_t pid, id_t lwpid) 241 { 242 plwp_t *elm, *elm_prev; 243 int hash = pid % PLWP_TBL_SZ; 244 245 elm = plwp_tbl[hash]; 246 elm_prev = NULL; 247 248 while (elm) { 249 if ((elm->l_pid == pid) && (elm->l_lwpid == lwpid)) { 250 if (!elm_prev) /* first chain element */ 251 plwp_tbl[hash] = elm->l_next; 252 else 253 elm_prev->l_next = elm->l_next; 254 free(elm); 255 break; 256 } else { 257 elm_prev = elm; 258 elm = elm->l_next; 259 } 260 } 261 } 262 263 static plwp_t * 264 lwpid_getptr(pid_t pid, id_t lwpid) 265 { 266 plwp_t *elm = plwp_tbl[pid % PLWP_TBL_SZ]; 267 while (elm) { 268 if ((elm->l_pid == pid) && (elm->l_lwpid == lwpid)) 269 return (elm); 270 else 271 elm = elm->l_next; 272 } 273 return (NULL); 274 } 275 276 lwp_info_t * 277 lwpid_get(pid_t pid, id_t lwpid) 278 { 279 plwp_t *elm = lwpid_getptr(pid, lwpid); 280 if (elm) 281 return (elm->l_lwp); 282 else 283 return (NULL); 284 } 285 286 int 287 lwpid_pidcheck(pid_t pid) 288 { 289 plwp_t *elm; 290 elm = plwp_tbl[pid % PLWP_TBL_SZ]; 291 while (elm) { 292 if (elm->l_pid == pid) 293 return (1); 294 else 295 elm = elm->l_next; 296 } 297 return (0); 298 } 299 300 int 301 lwpid_is_active(pid_t pid, id_t lwpid) 302 { 303 plwp_t *elm = lwpid_getptr(pid, lwpid); 304 if (elm) 305 return (elm->l_active); 306 else 307 return (0); 308 } 309 310 void 311 lwpid_set_active(pid_t pid, id_t lwpid) 312 { 313 plwp_t *elm = lwpid_getptr(pid, lwpid); 314 if (elm) 315 elm->l_active = LWP_ACTIVE; 316 } 317