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