Home | History | Annotate | Download | only in prstat
      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