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