print.c revision 225868
153541Sshin/*-
253541Sshin * Copyright (c) 1990, 1993, 1994
353541Sshin *	The Regents of the University of California.  All rights reserved.
453541Sshin *
553541Sshin * Redistribution and use in source and binary forms, with or without
653541Sshin * modification, are permitted provided that the following conditions
753541Sshin * are met:
853541Sshin * 1. Redistributions of source code must retain the above copyright
953541Sshin *    notice, this list of conditions and the following disclaimer.
1053541Sshin * 2. Redistributions in binary form must reproduce the above copyright
1153541Sshin *    notice, this list of conditions and the following disclaimer in the
1253541Sshin *    documentation and/or other materials provided with the distribution.
1353541Sshin * 4. Neither the name of the University nor the names of its contributors
1453541Sshin *    may be used to endorse or promote products derived from this software
1553541Sshin *    without specific prior written permission.
1653541Sshin *
1753541Sshin * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
1853541Sshin * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1953541Sshin * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2053541Sshin * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2153541Sshin * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2253541Sshin * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2353541Sshin * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2453541Sshin * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2553541Sshin * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2653541Sshin * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2753541Sshin * SUCH DAMAGE.
2853541Sshin */
2953541Sshin
3053541Sshin#if 0
3153541Sshin#ifndef lint
3253541Sshinstatic char sccsid[] = "@(#)print.c	8.6 (Berkeley) 4/16/94";
3353541Sshin#endif /* not lint */
3453541Sshin#endif
3553541Sshin
3653541Sshin#include <sys/cdefs.h>
3753541Sshin__FBSDID("$FreeBSD: head/bin/ps/print.c 225868 2011-09-29 06:31:42Z trasz $");
3853541Sshin
3953541Sshin#include <sys/param.h>
4053541Sshin#include <sys/time.h>
4153541Sshin#include <sys/resource.h>
4253541Sshin#include <sys/proc.h>
4353541Sshin#include <sys/stat.h>
4453541Sshin
4553541Sshin#include <sys/mac.h>
4653541Sshin#include <sys/user.h>
4753541Sshin#include <sys/sysctl.h>
4853541Sshin#include <sys/vmmeter.h>
4953541Sshin
5053541Sshin#include <err.h>
5153541Sshin#include <grp.h>
5253541Sshin#include <langinfo.h>
5353541Sshin#include <locale.h>
5453541Sshin#include <math.h>
5553541Sshin#include <nlist.h>
5653541Sshin#include <pwd.h>
5753541Sshin#include <stddef.h>
5853541Sshin#include <stdint.h>
5953541Sshin#include <stdio.h>
6053541Sshin#include <stdlib.h>
6153541Sshin#include <string.h>
6253541Sshin#include <unistd.h>
6353541Sshin#include <vis.h>
6453541Sshin
6553541Sshin#include "ps.h"
6653541Sshin
6755009Sshin#define	COMMAND_WIDTH	16
6878064Sume#define	ARGUMENTS_WIDTH	16
6955009Sshin
7053541Sshin#define	ps_pgtok(a)	(((a) * getpagesize()) / 1024)
7195759Stanimura
7295759Stanimuravoid
7353541Sshinprintheader(void)
7495759Stanimura{
7553541Sshin	VAR *v;
7695759Stanimura	struct varent *vent;
7795759Stanimura
7853541Sshin	STAILQ_FOREACH(vent, &varlist, next_ve)
7953541Sshin		if (*vent->header != '\0')
8095759Stanimura			break;
8153541Sshin	if (!vent)
8253541Sshin		return;
8353541Sshin
8495759Stanimura	STAILQ_FOREACH(vent, &varlist, next_ve) {
8553541Sshin		v = vent->var;
8653541Sshin		if (v->flag & LJUST) {
8753541Sshin			if (STAILQ_NEXT(vent, next_ve) == NULL)	/* last one */
8853541Sshin				(void)printf("%s", vent->header);
8953541Sshin			else
9095759Stanimura				(void)printf("%-*s", v->width, vent->header);
9195759Stanimura		} else
9262587Sitojun			(void)printf("%*s", v->width, vent->header);
9395759Stanimura		if (STAILQ_NEXT(vent, next_ve) != NULL)
9456723Sshin			(void)putchar(' ');
9553541Sshin	}
9695759Stanimura	(void)putchar('\n');
9753541Sshin}
9895759Stanimura
9962587Sitojunchar *
10062587Sitojunarguments(KINFO *k, VARENT *ve)
10162587Sitojun{
10253541Sshin	VAR *v;
10353541Sshin	char *vis_args;
10453541Sshin
10553541Sshin	v = ve->var;
10653541Sshin	if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
10753541Sshin		errx(1, "malloc failed");
108105199Ssam	strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
109105199Ssam
110105199Ssam	if (STAILQ_NEXT(ve, next_ve) != NULL && strlen(vis_args) > ARGUMENTS_WIDTH)
111105199Ssam		vis_args[ARGUMENTS_WIDTH] = '\0';
112105199Ssam
11353541Sshin	return (vis_args);
11453541Sshin}
11553541Sshin
11653541Sshinchar *
11753541Sshincommand(KINFO *k, VARENT *ve)
11853541Sshin{
11953541Sshin	VAR *v;
12053541Sshin	char *vis_args, *vis_env, *str;
12153541Sshin
12253541Sshin	v = ve->var;
12353541Sshin	if (cflag) {
12453541Sshin		/* If it is the last field, then don't pad */
12553541Sshin		if (STAILQ_NEXT(ve, next_ve) == NULL) {
12653541Sshin			asprintf(&str, "%s%s%s%s",
12778064Sume			    k->ki_d.prefix ? k->ki_d.prefix : "",
12878064Sume			    k->ki_p->ki_comm,
12953541Sshin			    (showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
13053541Sshin			    (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "");
13153541Sshin		} else
13253541Sshin			str = strdup(k->ki_p->ki_comm);
13353541Sshin
13453541Sshin		return (str);
13553541Sshin	}
13653541Sshin	if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
13753541Sshin		errx(1, "malloc failed");
13853541Sshin	strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
13953541Sshin
14053541Sshin	if (STAILQ_NEXT(ve, next_ve) == NULL) {
14153541Sshin		/* last field */
14253541Sshin
14378064Sume		if (k->ki_env) {
14453541Sshin			if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1))
14553541Sshin			    == NULL)
14678064Sume				errx(1, "malloc failed");
14778064Sume			strvis(vis_env, k->ki_env,
14883934Sbrooks			    VIS_TAB | VIS_NL | VIS_NOSLASH);
14978064Sume		} else
15078064Sume			vis_env = NULL;
15178064Sume
15253541Sshin		asprintf(&str, "%s%s%s%s",
15378064Sume		    k->ki_d.prefix ? k->ki_d.prefix : "",
15453541Sshin		    vis_env ? vis_env : "",
15553541Sshin		    vis_env ? " " : "",
15653541Sshin		    vis_args);
15755009Sshin
15853541Sshin		if (vis_env != NULL)
15953541Sshin			free(vis_env);
16053541Sshin		free(vis_args);
16153541Sshin	} else {
16253541Sshin		/* ki_d.prefix & ki_env aren't shown for interim fields */
16353541Sshin		str = vis_args;
16453541Sshin
16553541Sshin		if (strlen(str) > COMMAND_WIDTH)
16653541Sshin			str[COMMAND_WIDTH] = '\0';
16753541Sshin	}
16878064Sume
16978064Sume	return (str);
17078064Sume}
17178064Sume
17278064Sumechar *
17378064Sumeucomm(KINFO *k, VARENT *ve)
17478064Sume{
17553541Sshin	VAR *v;
17653541Sshin	char *str;
17753541Sshin
17878064Sume	v = ve->var;
17978064Sume	if (STAILQ_NEXT(ve, next_ve) == NULL) {	/* last field, don't pad */
18078064Sume		asprintf(&str, "%s%s%s%s",
18178064Sume		    k->ki_d.prefix ? k->ki_d.prefix : "",
18278064Sume		    k->ki_p->ki_comm,
183111145Sjlemon		    (showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
18478064Sume		    (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "");
18578064Sume	} else {
18678064Sume		if (showthreads && k->ki_p->ki_numthreads > 1)
18778064Sume			asprintf(&str, "%s/%s", k->ki_p->ki_comm, k->ki_p->ki_tdname);
18878064Sume		else
189105199Ssam			str = strdup(k->ki_p->ki_comm);
190105199Ssam	}
191105199Ssam	return (str);
192105199Ssam}
193105199Ssam
194105199Ssamchar *
195105199Ssamtdnam(KINFO *k, VARENT *ve)
196105199Ssam{
197105199Ssam	VAR *v;
19853541Sshin	char *str;
19997658Stanimura
20097658Stanimura	v = ve->var;
20153541Sshin	if (showthreads && k->ki_p->ki_numthreads > 1)
20253541Sshin		str = strdup(k->ki_p->ki_tdname);
20353541Sshin	else
20453541Sshin		str = strdup("      ");
20553541Sshin
20653541Sshin	return (str);
20753541Sshin}
20853541Sshin
20953541Sshinchar *
21078064Sumelogname(KINFO *k, VARENT *ve)
21197658Stanimura{
21253541Sshin	VAR *v;
21353541Sshin
21453541Sshin	v = ve->var;
21553541Sshin	if (*k->ki_p->ki_login == '\0')
21653541Sshin		return (NULL);
21753541Sshin	return (strdup(k->ki_p->ki_login));
21878064Sume}
21978064Sume
22078064Sumechar *
22178064Sumestate(KINFO *k, VARENT *ve)
222111145Sjlemon{
22378064Sume	int flag, tdflags;
22478064Sume	char *cp, *buf;
22578064Sume	VAR *v;
22678064Sume
22778064Sume	buf = malloc(16);
22878064Sume	if (buf == NULL)
229105199Ssam		errx(1, "malloc failed");
230105199Ssam
231105199Ssam	v = ve->var;
232105199Ssam	flag = k->ki_p->ki_flag;
233105199Ssam	tdflags = k->ki_p->ki_tdflags;	/* XXXKSE */
234105199Ssam	cp = buf;
235105199Ssam
236105199Ssam	switch (k->ki_p->ki_stat) {
237105199Ssam
238105199Ssam	case SSTOP:
23953541Sshin		*cp = 'T';
24097658Stanimura		break;
24197658Stanimura
24253541Sshin	case SSLEEP:
24353541Sshin		if (tdflags & TDF_SINTR)	/* interruptable (long) */
24453541Sshin			*cp = k->ki_p->ki_slptime >= MAXSLP ? 'I' : 'S';
24553541Sshin		else
24653541Sshin			*cp = 'D';
24753541Sshin		break;
24853541Sshin
24953541Sshin	case SRUN:
25078064Sume	case SIDL:
25197658Stanimura		*cp = 'R';
25253541Sshin		break;
25353541Sshin
25478064Sume	case SWAIT:
25578064Sume		*cp = 'W';
25678064Sume		break;
25753541Sshin
25853541Sshin	case SLOCK:
25953541Sshin		*cp = 'L';
26053541Sshin		break;
26153541Sshin
26253541Sshin	case SZOMB:
26353541Sshin		*cp = 'Z';
26453541Sshin		break;
26553541Sshin
26653541Sshin	default:
26753541Sshin		*cp = '?';
26853541Sshin	}
26953541Sshin	cp++;
27062587Sitojun	if (!(flag & P_INMEM))
27162587Sitojun		*cp++ = 'W';
27262587Sitojun	if (k->ki_p->ki_nice < NZERO)
27362587Sitojun		*cp++ = '<';
27462587Sitojun	else if (k->ki_p->ki_nice > NZERO)
27562587Sitojun		*cp++ = 'N';
27662587Sitojun	if (flag & P_TRACED)
27762587Sitojun		*cp++ = 'X';
27862587Sitojun	if (flag & P_WEXIT && k->ki_p->ki_stat != SZOMB)
27978064Sume		*cp++ = 'E';
28078064Sume	if (flag & P_PPWAIT)
28198211Shsu		*cp++ = 'V';
28262587Sitojun	if ((flag & P_SYSTEM) || k->ki_p->ki_lock > 0)
28362587Sitojun		*cp++ = 'L';
28462587Sitojun	if (k->ki_p->ki_kiflag & KI_SLEADER)
28562587Sitojun		*cp++ = 's';
28662587Sitojun	if ((flag & P_CONTROLT) && k->ki_p->ki_pgid == k->ki_p->ki_tpgid)
28762587Sitojun		*cp++ = '+';
28862587Sitojun	if (flag & P_JAILED)
28962587Sitojun		*cp++ = 'J';
29062587Sitojun	*cp = '\0';
29162587Sitojun	return (buf);
29262587Sitojun}
29362587Sitojun
29462587Sitojun#define	scalepri(x)	((x) - PZERO)
29562587Sitojun
29662587Sitojunchar *
29762587Sitojunpri(KINFO *k, VARENT *ve)
29878064Sume{
29962587Sitojun	VAR *v;
30062587Sitojun	char *str;
30162587Sitojun
30278064Sume	v = ve->var;
30362587Sitojun	asprintf(&str, "%d", scalepri(k->ki_p->ki_pri.pri_level));
30462587Sitojun	return (str);
30562587Sitojun}
30678064Sume
30762587Sitojunchar *
30862587Sitojunupr(KINFO *k, VARENT *ve)
30991346Salfred{
31078064Sume	VAR *v;
31162587Sitojun	char *str;
31262587Sitojun
31353541Sshin	v = ve->var;
31453541Sshin	asprintf(&str, "%d", scalepri(k->ki_p->ki_pri.pri_user));
31553541Sshin	return (str);
31653541Sshin}
31753541Sshin#undef scalepri
31853541Sshin
31953541Sshinchar *
32053541Sshinuname(KINFO *k, VARENT *ve)
32153541Sshin{
32253541Sshin	VAR *v;
32353541Sshin
32453541Sshin	v = ve->var;
32553541Sshin	return (strdup(user_from_uid(k->ki_p->ki_uid, 0)));
326120941Sume}
32753541Sshin
32853541Sshinchar *
32953541Sshinegroupname(KINFO *k, VARENT *ve)
33053541Sshin{
33153541Sshin	VAR *v;
33253541Sshin
33353541Sshin	v = ve->var;
334121472Sume	return (strdup(group_from_gid(k->ki_p->ki_groups[0], 0)));
33553541Sshin}
33653541Sshin
33753541Sshinchar *
338121472Sumergroupname(KINFO *k, VARENT *ve)
33953541Sshin{
34053541Sshin	VAR *v;
34153541Sshin
34253541Sshin	v = ve->var;
34353541Sshin	return (strdup(group_from_gid(k->ki_p->ki_rgid, 0)));
34453541Sshin}
34553541Sshin
34653541Sshinchar *
34753541Sshinruname(KINFO *k, VARENT *ve)
348121472Sume{
34953541Sshin	VAR *v;
35053541Sshin
35153541Sshin	v = ve->var;
35253541Sshin	return (strdup(user_from_uid(k->ki_p->ki_ruid, 0)));
35353541Sshin}
35453541Sshin
355121472Sumechar *
356121472Sumetdev(KINFO *k, VARENT *ve)
357121472Sume{
358121472Sume	VAR *v;
35953541Sshin	dev_t dev;
360121472Sume	char *str;
361121472Sume
362121472Sume	v = ve->var;
36353541Sshin	dev = k->ki_p->ki_tdev;
36453541Sshin	if (dev == NODEV)
36553541Sshin		str = strdup("??");
36653541Sshin	else
36753541Sshin		asprintf(&str, "%#jx", (uintmax_t)dev);
36853541Sshin
36953541Sshin	return (str);
37053541Sshin}
37153541Sshin
37253541Sshinchar *
37353541Sshintname(KINFO *k, VARENT *ve)
37453541Sshin{
37553541Sshin	VAR *v;
37653541Sshin	dev_t dev;
37753541Sshin	char *ttname, *str;
37853541Sshin
37953541Sshin	v = ve->var;
380111119Simp	dev = k->ki_p->ki_tdev;
38153541Sshin	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
38253541Sshin		str = strdup("?? ");
38353541Sshin	else {
38453541Sshin		if (strncmp(ttname, "tty", 3) == 0 ||
38553541Sshin		    strncmp(ttname, "cua", 3) == 0)
38653541Sshin			ttname += 3;
38753541Sshin		if (strncmp(ttname, "pts/", 4) == 0)
38853541Sshin			ttname += 4;
38953541Sshin		asprintf(&str, "%s%c", ttname,
39053541Sshin		    k->ki_p->ki_kiflag & KI_CTTY ? ' ' : '-');
39153541Sshin	}
39253541Sshin
39353541Sshin	return (str);
39453541Sshin}
39553541Sshin
39653541Sshinchar *
39753541Sshinlongtname(KINFO *k, VARENT *ve)
39853541Sshin{
39953541Sshin	VAR *v;
40053541Sshin	dev_t dev;
401121472Sume	const char *ttname;
402121472Sume
403121472Sume	v = ve->var;
40453541Sshin	dev = k->ki_p->ki_tdev;
40583130Sjlemon	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
40653541Sshin		ttname = "??";
40753541Sshin
40853541Sshin	return (strdup(ttname));
40953541Sshin}
41053541Sshin
41153541Sshinchar *
41253541Sshinstarted(KINFO *k, VARENT *ve)
413120941Sume{
414120941Sume	VAR *v;
41553541Sshin	time_t then;
41653541Sshin	struct tm *tp;
41753541Sshin	static int use_ampm = -1;
418120941Sume	size_t buflen = 100;
419120941Sume	char *buf;
42053541Sshin
42153541Sshin	buf = malloc(buflen);
42253541Sshin	if (buf == NULL)
42353541Sshin		errx(1, "malloc failed");
42453541Sshin
42553541Sshin	v = ve->var;
426121472Sume	if (!k->ki_valid)
427121472Sume		return (NULL);
428121472Sume	if (use_ampm < 0)
429121472Sume		use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0');
430121472Sume	then = k->ki_p->ki_start.tv_sec;
431121472Sume	tp = localtime(&then);
43253541Sshin	if (now - k->ki_p->ki_start.tv_sec < 24 * 3600) {
433121472Sume		(void)strftime(buf, buflen,
434121472Sume		    use_ampm ? "%l:%M%p" : "%k:%M  ", tp);
435121472Sume	} else if (now - k->ki_p->ki_start.tv_sec < 7 * 86400) {
43655009Sshin		(void)strftime(buf, buflen,
43755009Sshin		    use_ampm ? "%a%I%p" : "%a%H  ", tp);
43855009Sshin	} else
43955009Sshin		(void)strftime(buf, buflen, "%e%b%y", tp);
44053541Sshin	return (buf);
44153541Sshin}
44253541Sshin
44353541Sshinchar *
44453541Sshinlstarted(KINFO *k, VARENT *ve)
44553541Sshin{
44653541Sshin	VAR *v;
44753541Sshin	time_t then;
44853541Sshin	char *buf;
44953541Sshin	size_t buflen = 100;
45053541Sshin
45153541Sshin	buf = malloc(buflen);
45253541Sshin	if (buf == NULL)
45353541Sshin		errx(1, "malloc failed");
45453541Sshin
45553541Sshin	v = ve->var;
45653541Sshin	if (!k->ki_valid)
45753541Sshin		return (NULL);
45853541Sshin	then = k->ki_p->ki_start.tv_sec;
45953541Sshin	(void)strftime(buf, buflen, "%c", localtime(&then));
46053541Sshin	return (buf);
46153541Sshin}
46253541Sshin
46353541Sshinchar *
46453541Sshinlockname(KINFO *k, VARENT *ve)
46553541Sshin{
46653541Sshin	VAR *v;
46753541Sshin	char *str;
46853541Sshin
46953541Sshin	v = ve->var;
47053541Sshin	if (k->ki_p->ki_kiflag & KI_LOCKBLOCK) {
47153541Sshin		if (k->ki_p->ki_lockname[0] != 0)
47253541Sshin			str = strdup(k->ki_p->ki_lockname);
473121472Sume		else
474105194Ssam			str = strdup("???");
47553541Sshin	} else
47653541Sshin		str = NULL;
47753541Sshin
47853541Sshin	return (str);
47978064Sume}
48078064Sume
48153541Sshinchar *
48253541Sshinwchan(KINFO *k, VARENT *ve)
48353541Sshin{
48453541Sshin	VAR *v;
48553541Sshin	char *str;
48653541Sshin
48753541Sshin	v = ve->var;
48853541Sshin	if (k->ki_p->ki_wchan) {
48978064Sume		if (k->ki_p->ki_wmesg[0] != 0)
490121472Sume			str = strdup(k->ki_p->ki_wmesg);
491121472Sume		else
49253541Sshin			asprintf(&str, "%lx", (long)k->ki_p->ki_wchan);
49378064Sume	} else
494120856Sume		str = NULL;
49553541Sshin
49653541Sshin	return (str);
49753541Sshin}
49853541Sshin
49953541Sshinchar *
50053541Sshinnwchan(KINFO *k, VARENT *ve)
50153541Sshin{
50253541Sshin	VAR *v;
50353541Sshin	char *str;
50453541Sshin
50553541Sshin	v = ve->var;
50653541Sshin	if (k->ki_p->ki_wchan)
50753541Sshin		asprintf(&str, "%0lx", (long)k->ki_p->ki_wchan);
50853541Sshin	else
50953541Sshin		str = NULL;
51053541Sshin
51153541Sshin	return (str);
512120856Sume}
51353541Sshin
51453541Sshinchar *
51553541Sshinmwchan(KINFO *k, VARENT *ve)
51653541Sshin{
51753541Sshin	VAR *v;
51853541Sshin	char *str;
51953541Sshin
52053541Sshin	v = ve->var;
52156723Sshin	if (k->ki_p->ki_wchan) {
52256723Sshin		if (k->ki_p->ki_wmesg[0] != 0)
52356723Sshin			str = strdup(k->ki_p->ki_wmesg);
52456723Sshin		else
52556723Sshin                        asprintf(&str, "%lx", (long)k->ki_p->ki_wchan);
52656723Sshin	} else if (k->ki_p->ki_kiflag & KI_LOCKBLOCK) {
52756723Sshin		if (k->ki_p->ki_lockname[0]) {
52856723Sshin			str = strdup(k->ki_p->ki_lockname);
52956723Sshin		} else
530121578Sume			str = strdup("???");
531121578Sume	} else
532121578Sume		str = NULL;
53353541Sshin
53453541Sshin	return (str);
53553541Sshin}
53653541Sshin
53753541Sshinchar *
53853541Sshinvsize(KINFO *k, VARENT *ve)
53953541Sshin{
54053541Sshin	VAR *v;
54156723Sshin	char *str;
54256723Sshin
54356723Sshin	v = ve->var;
54456723Sshin	asprintf(&str, "%lu", (u_long)(k->ki_p->ki_size / 1024));
54556723Sshin	return (str);
54656723Sshin}
54756723Sshin
54856723Sshinstatic char *
54956723Sshinprinttime(KINFO *k, VARENT *ve, long secs, long psecs)
550121578Sume/* psecs is "parts" of a second. first micro, then centi */
551121578Sume{
552121578Sume	VAR *v;
55353541Sshin	static char decimal_point;
55453541Sshin	char *str;
55553541Sshin
55653541Sshin	if (decimal_point == '\0')
55753541Sshin		decimal_point = localeconv()->decimal_point[0];
55853541Sshin	v = ve->var;
55953541Sshin	if (!k->ki_valid) {
56053541Sshin		secs = 0;
56153541Sshin		psecs = 0;
56253541Sshin	} else {
56353541Sshin		/* round and scale to 100's */
56483366Sjulian		psecs = (psecs + 5000) / 10000;
56553541Sshin		secs += psecs / 100;
56653541Sshin		psecs = psecs % 100;
56753541Sshin	}
56853541Sshin	asprintf(&str, "%ld:%02ld%c%02ld",
56953541Sshin	    secs / 60, secs % 60, decimal_point, psecs);
57053541Sshin	return (str);
57153541Sshin}
57293593Sjhb
57353541Sshinchar *
57453541Sshincputime(KINFO *k, VARENT *ve)
57555009Sshin{
57655009Sshin	long secs, psecs;
57755009Sshin
57853541Sshin	/*
57983366Sjulian	 * This counts time spent handling interrupts.  We could
58053541Sshin	 * fix this, but it is not 100% trivial (and interrupt
58153541Sshin	 * time fractions only work on the sparc anyway).	XXX
58253541Sshin	 */
58353541Sshin	secs = k->ki_p->ki_runtime / 1000000;
58453541Sshin	psecs = k->ki_p->ki_runtime % 1000000;
58553541Sshin	if (sumrusage) {
58653541Sshin		secs += k->ki_p->ki_childtime.tv_sec;
58753541Sshin		psecs += k->ki_p->ki_childtime.tv_usec;
58853541Sshin	}
58953541Sshin	return (printtime(k, ve, secs, psecs));
59053541Sshin}
59153541Sshin
59253541Sshinchar *
59353541Sshinsystime(KINFO *k, VARENT *ve)
59453541Sshin{
59553541Sshin	long secs, psecs;
59653541Sshin
59753541Sshin	secs = k->ki_p->ki_rusage.ru_stime.tv_sec;
59853541Sshin	psecs = k->ki_p->ki_rusage.ru_stime.tv_usec;
59953541Sshin	if (sumrusage) {
60053541Sshin		secs += k->ki_p->ki_childstime.tv_sec;
60153541Sshin		psecs += k->ki_p->ki_childstime.tv_usec;
60253541Sshin	}
60357535Sshin	return (printtime(k, ve, secs, psecs));
60457535Sshin}
60553541Sshin
60653541Sshinchar *
60753541Sshinusertime(KINFO *k, VARENT *ve)
60853541Sshin{
60953541Sshin	long secs, psecs;
61053541Sshin
61153541Sshin	secs = k->ki_p->ki_rusage.ru_utime.tv_sec;
61253541Sshin	psecs = k->ki_p->ki_rusage.ru_utime.tv_usec;
61353541Sshin	if (sumrusage) {
61453541Sshin		secs += k->ki_p->ki_childutime.tv_sec;
61553541Sshin		psecs += k->ki_p->ki_childutime.tv_usec;
61653541Sshin	}
61753541Sshin	return (printtime(k, ve, secs, psecs));
61853541Sshin}
61953541Sshin
62053541Sshinchar *
62153541Sshinelapsed(KINFO *k, VARENT *ve)
62253541Sshin{
62353541Sshin	VAR *v;
62453541Sshin	time_t val;
62597658Stanimura	int days, hours, mins, secs;
62653541Sshin	char *str;
62753541Sshin
62853541Sshin	v = ve->var;
62953541Sshin	if (!k->ki_valid)
63053541Sshin		return (NULL);
63153541Sshin	val = now - k->ki_p->ki_start.tv_sec;
63283366Sjulian	days = val / (24 * 60 * 60);
63353541Sshin	val %= 24 * 60 * 60;
63453541Sshin	hours = val / (60 * 60);
63553541Sshin	val %= 60 * 60;
63653541Sshin	mins = val / 60;
63753541Sshin	secs = val % 60;
63853541Sshin	if (days != 0)
63953541Sshin		asprintf(&str, "%3d-%02d:%02d:%02d", days, hours, mins, secs);
64053541Sshin	else if (hours != 0)
64153541Sshin		asprintf(&str, "%02d:%02d:%02d", hours, mins, secs);
64262587Sitojun	else
64362587Sitojun		asprintf(&str, "%02d:%02d", mins, secs);
64462587Sitojun
64562587Sitojun	return (str);
64662587Sitojun}
64753541Sshin
64853541Sshinchar *
64953541Sshinelapseds(KINFO *k, VARENT *ve)
65053541Sshin{
65153541Sshin	VAR *v;
65253541Sshin	time_t val;
65353541Sshin	char *str;
654120856Sume
65553541Sshin	v = ve->var;
65653541Sshin	if (!k->ki_valid)
65753541Sshin		return (NULL);
65853541Sshin	val = now - k->ki_p->ki_start.tv_sec;
65953541Sshin	asprintf(&str, "%jd", (intmax_t)val);
66053541Sshin	return (str);
66183366Sjulian}
66253541Sshin
66353541Sshindouble
66453541Sshingetpcpu(const KINFO *k)
66553541Sshin{
66653541Sshin	static int failure;
66762587Sitojun
66862587Sitojun	if (!nlistread)
66962587Sitojun		failure = donlist();
67053541Sshin	if (failure)
67153541Sshin		return (0.0);
67253541Sshin
67353541Sshin#define	fxtofl(fixpt)	((double)(fixpt) / fscale)
67453541Sshin
67553541Sshin	/* XXX - I don't like this */
67653541Sshin	if (k->ki_p->ki_swtime == 0 || (k->ki_p->ki_flag & P_INMEM) == 0)
67762587Sitojun		return (0.0);
67862587Sitojun	if (rawcpu)
67962587Sitojun		return (100.0 * fxtofl(k->ki_p->ki_pctcpu));
68062587Sitojun	return (100.0 * fxtofl(k->ki_p->ki_pctcpu) /
68162587Sitojun		(1.0 - exp(k->ki_p->ki_swtime * log(fxtofl(ccpu)))));
68262587Sitojun}
68362587Sitojun
68462587Sitojunchar *
68553541Sshinpcpu(KINFO *k, VARENT *ve)
68653541Sshin{
68753541Sshin	VAR *v;
68853541Sshin	char *str;
68953541Sshin
69053541Sshin	v = ve->var;
69153541Sshin	asprintf(&str, "%.1f", getpcpu(k));
69253541Sshin	return (str);
69353541Sshin}
69453541Sshin
69553541Sshinstatic double
69653541Sshingetpmem(KINFO *k)
69753541Sshin{
69853541Sshin	static int failure;
69953541Sshin	double fracmem;
70053541Sshin
70153541Sshin	if (!nlistread)
70253541Sshin		failure = donlist();
70353541Sshin	if (failure)
70453541Sshin		return (0.0);
70553541Sshin
70683366Sjulian	if ((k->ki_p->ki_flag & P_INMEM) == 0)
70753541Sshin		return (0.0);
70853541Sshin	/* XXX want pmap ptpages, segtab, etc. (per architecture) */
70953541Sshin	/* XXX don't have info about shared */
71053541Sshin	fracmem = ((float)k->ki_p->ki_rssize) / mempages;
71153541Sshin	return (100.0 * fracmem);
71262587Sitojun}
71353541Sshin
71453541Sshinchar *
71553541Sshinpmem(KINFO *k, VARENT *ve)
71653541Sshin{
71753541Sshin	VAR *v;
71853541Sshin	char *str;
71953541Sshin
72053541Sshin	v = ve->var;
72153541Sshin	asprintf(&str, "%.1f", getpmem(k));
72253541Sshin	return (str);
72353541Sshin}
72453541Sshin
72553541Sshinchar *
72653541Sshinpagein(KINFO *k, VARENT *ve)
72753541Sshin{
72853541Sshin	VAR *v;
72953541Sshin	char *str;
73062587Sitojun
73162587Sitojun	v = ve->var;
73253541Sshin	asprintf(&str, "%ld", k->ki_valid ? k->ki_p->ki_rusage.ru_majflt : 0);
73362587Sitojun	return (str);
73462587Sitojun}
73562587Sitojun
73662587Sitojun/* ARGSUSED */
73762587Sitojunchar *
73853541Sshinmaxrss(KINFO *k __unused, VARENT *ve)
73953541Sshin{
74053541Sshin	VAR *v;
74153541Sshin
74253541Sshin	v = ve->var;
74353541Sshin	/* XXX not yet */
74453541Sshin	return (NULL);
74553541Sshin}
74653541Sshin
74753541Sshinchar *
748priorityr(KINFO *k, VARENT *ve)
749{
750	VAR *v;
751	struct priority *lpri;
752	char *str;
753	unsigned class, level;
754
755	v = ve->var;
756	lpri = &k->ki_p->ki_pri;
757	class = lpri->pri_class;
758	level = lpri->pri_level;
759	switch (class) {
760	case PRI_ITHD:
761		asprintf(&str, "intr:%u", level);
762		break;
763	case PRI_REALTIME:
764		asprintf(&str, "real:%u", level);
765		break;
766	case PRI_TIMESHARE:
767		asprintf(&str, "normal");
768		break;
769	case PRI_IDLE:
770		asprintf(&str, "idle:%u", level);
771		break;
772	default:
773		asprintf(&str, "%u:%u", class, level);
774		break;
775	}
776	return (str);
777}
778
779/*
780 * Generic output routines.  Print fields from various prototype
781 * structures.
782 */
783static char *
784printval(void *bp, VAR *v)
785{
786	static char ofmt[32] = "%";
787	const char *fcp;
788	char *cp, *str;
789
790	cp = ofmt + 1;
791	fcp = v->fmt;
792	while ((*cp++ = *fcp++));
793
794#define	CHKINF127(n)	(((n) > 127) && (v->flag & INF127) ? 127 : (n))
795
796	switch (v->type) {
797	case CHAR:
798		(void)asprintf(&str, ofmt, *(char *)bp);
799		break;
800	case UCHAR:
801		(void)asprintf(&str, ofmt, *(u_char *)bp);
802		break;
803	case SHORT:
804		(void)asprintf(&str, ofmt, *(short *)bp);
805		break;
806	case USHORT:
807		(void)asprintf(&str, ofmt, *(u_short *)bp);
808		break;
809	case INT:
810		(void)asprintf(&str, ofmt, *(int *)bp);
811		break;
812	case UINT:
813		(void)asprintf(&str, ofmt, CHKINF127(*(u_int *)bp));
814		break;
815	case LONG:
816		(void)asprintf(&str, ofmt, *(long *)bp);
817		break;
818	case ULONG:
819		(void)asprintf(&str, ofmt, *(u_long *)bp);
820		break;
821	case KPTR:
822		(void)asprintf(&str, ofmt, *(u_long *)bp);
823		break;
824	case PGTOK:
825		(void)asprintf(&str, ofmt, ps_pgtok(*(u_long *)bp));
826		break;
827	default:
828		errx(1, "unknown type %d", v->type);
829	}
830
831	return (str);
832}
833
834char *
835kvar(KINFO *k, VARENT *ve)
836{
837	VAR *v;
838
839	v = ve->var;
840	return (printval((char *)((char *)k->ki_p + v->off), v));
841}
842
843char *
844rvar(KINFO *k, VARENT *ve)
845{
846	VAR *v;
847
848	v = ve->var;
849	if (!k->ki_valid)
850		return (NULL);
851	return (printval((char *)((char *)(&k->ki_p->ki_rusage) + v->off), v));
852}
853
854char *
855emulname(KINFO *k, VARENT *ve)
856{
857	VAR *v;
858
859	v = ve->var;
860	if (k->ki_p->ki_emul == NULL)
861		return (NULL);
862	return (strdup(k->ki_p->ki_emul));
863}
864
865char *
866label(KINFO *k, VARENT *ve)
867{
868	char *string;
869	VAR *v;
870	mac_t proclabel;
871	int error;
872
873	v = ve->var;
874	string = NULL;
875	if (mac_prepare_process_label(&proclabel) == -1) {
876		warn("mac_prepare_process_label");
877		goto out;
878	}
879	error = mac_get_pid(k->ki_p->ki_pid, proclabel);
880	if (error == 0) {
881		if (mac_to_text(proclabel, &string) == -1)
882			string = NULL;
883	}
884	mac_free(proclabel);
885out:
886	return (string);
887}
888
889char *
890loginclass(KINFO *k, VARENT *ve)
891{
892	VAR *v;
893	char *s;
894
895	v = ve->var;
896	/*
897	 * Don't display login class for system processes;
898	 * login classes are used for resource limits,
899	 * and limits don't apply to system processes.
900	 */
901	if (k->ki_p->ki_flag & P_SYSTEM) {
902		return (strdup("-"));
903	}
904	s = k->ki_p->ki_loginclass;
905	if (s == NULL)
906		return (NULL);
907	return (strdup(s));
908}
909