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