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