11556Srgrimes/*-
21556Srgrimes * Copyright (c) 1990, 1993, 1994
31556Srgrimes *	The Regents of the University of California.  All rights reserved.
41556Srgrimes *
51556Srgrimes * Redistribution and use in source and binary forms, with or without
61556Srgrimes * modification, are permitted provided that the following conditions
71556Srgrimes * are met:
81556Srgrimes * 1. Redistributions of source code must retain the above copyright
91556Srgrimes *    notice, this list of conditions and the following disclaimer.
101556Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111556Srgrimes *    notice, this list of conditions and the following disclaimer in the
121556Srgrimes *    documentation and/or other materials provided with the distribution.
131556Srgrimes * 4. Neither the name of the University nor the names of its contributors
141556Srgrimes *    may be used to endorse or promote products derived from this software
151556Srgrimes *    without specific prior written permission.
161556Srgrimes *
171556Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
181556Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
191556Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
201556Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
211556Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
221556Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
231556Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
241556Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
251556Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
261556Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
271556Srgrimes * SUCH DAMAGE.
281556Srgrimes */
291556Srgrimes
3090143Smarkm#if 0
311556Srgrimes#ifndef lint
3236049Scharnierstatic char sccsid[] = "@(#)print.c	8.6 (Berkeley) 4/16/94";
3390143Smarkm#endif /* not lint */
3436049Scharnier#endif
35110391Scharnier
3699110Sobrien#include <sys/cdefs.h>
3799110Sobrien__FBSDID("$FreeBSD$");
381556Srgrimes
391556Srgrimes#include <sys/param.h>
401556Srgrimes#include <sys/time.h>
411556Srgrimes#include <sys/resource.h>
421556Srgrimes#include <sys/proc.h>
431556Srgrimes#include <sys/stat.h>
441556Srgrimes
45105831Srwatson#include <sys/mac.h>
4611890Sphk#include <sys/user.h>
471556Srgrimes#include <sys/sysctl.h>
48217192Skib#include <sys/vmmeter.h>
491556Srgrimes
501556Srgrimes#include <err.h>
5190878Simp#include <grp.h>
5273369Sache#include <langinfo.h>
5372343Sache#include <locale.h>
541556Srgrimes#include <math.h>
551556Srgrimes#include <nlist.h>
5690878Simp#include <pwd.h>
571556Srgrimes#include <stddef.h>
58205271Sjmallett#include <stdint.h>
591556Srgrimes#include <stdio.h>
601556Srgrimes#include <stdlib.h>
6190143Smarkm#include <string.h>
6216835Speter#include <unistd.h>
631556Srgrimes#include <vis.h>
641556Srgrimes
651556Srgrimes#include "ps.h"
661556Srgrimes
67225868Strasz#define	COMMAND_WIDTH	16
68225868Strasz#define	ARGUMENTS_WIDTH	16
69225868Strasz
70103274Speter#define	ps_pgtok(a)	(((a) * getpagesize()) / 1024)
7190143Smarkm
721556Srgrimesvoid
7390110Simpprintheader(void)
741556Srgrimes{
751556Srgrimes	VAR *v;
761556Srgrimes	struct varent *vent;
771556Srgrimes
78130999Sgad	STAILQ_FOREACH(vent, &varlist, next_ve)
79130999Sgad		if (*vent->header != '\0')
80106251Stjr			break;
81130999Sgad	if (!vent)
82106251Stjr		return;
83130999Sgad
84130999Sgad	STAILQ_FOREACH(vent, &varlist, next_ve) {
851556Srgrimes		v = vent->var;
861556Srgrimes		if (v->flag & LJUST) {
87130999Sgad			if (STAILQ_NEXT(vent, next_ve) == NULL)	/* last one */
88109504Sjmallett				(void)printf("%s", vent->header);
891556Srgrimes			else
90109504Sjmallett				(void)printf("%-*s", v->width, vent->header);
911556Srgrimes		} else
92109504Sjmallett			(void)printf("%*s", v->width, vent->header);
93130999Sgad		if (STAILQ_NEXT(vent, next_ve) != NULL)
941556Srgrimes			(void)putchar(' ');
951556Srgrimes	}
961556Srgrimes	(void)putchar('\n');
971556Srgrimes}
981556Srgrimes
99225868Straszchar *
10097958Sjmallettarguments(KINFO *k, VARENT *ve)
10197958Sjmallett{
102225868Strasz	char *vis_args;
10397958Sjmallett
10497958Sjmallett	if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
10597958Sjmallett		errx(1, "malloc failed");
10697958Sjmallett	strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
107225868Strasz
108225868Strasz	if (STAILQ_NEXT(ve, next_ve) != NULL && strlen(vis_args) > ARGUMENTS_WIDTH)
109225868Strasz		vis_args[ARGUMENTS_WIDTH] = '\0';
110225868Strasz
111225868Strasz	return (vis_args);
11297958Sjmallett}
11397958Sjmallett
114225868Straszchar *
11590110Simpcommand(KINFO *k, VARENT *ve)
1161556Srgrimes{
117225868Strasz	char *vis_args, *vis_env, *str;
1181556Srgrimes
11919068Speter	if (cflag) {
120130999Sgad		/* If it is the last field, then don't pad */
121173004Sjulian		if (STAILQ_NEXT(ve, next_ve) == NULL) {
122225868Strasz			asprintf(&str, "%s%s%s%s",
123225868Strasz			    k->ki_d.prefix ? k->ki_d.prefix : "",
124225868Strasz			    k->ki_p->ki_comm,
125225868Strasz			    (showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
126225868Strasz			    (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "");
127173004Sjulian		} else
128225868Strasz			str = strdup(k->ki_p->ki_comm);
129225868Strasz
130225868Strasz		return (str);
13119068Speter	}
1321556Srgrimes	if ((vis_args = malloc(strlen(k->ki_args) * 4 + 1)) == NULL)
13397877Sjmallett		errx(1, "malloc failed");
1341556Srgrimes	strvis(vis_args, k->ki_args, VIS_TAB | VIS_NL | VIS_NOSLASH);
1351556Srgrimes
136130999Sgad	if (STAILQ_NEXT(ve, next_ve) == NULL) {
1371556Srgrimes		/* last field */
138192239Sbrian
139192239Sbrian		if (k->ki_env) {
140192239Sbrian			if ((vis_env = malloc(strlen(k->ki_env) * 4 + 1))
141192239Sbrian			    == NULL)
142192239Sbrian				errx(1, "malloc failed");
143192239Sbrian			strvis(vis_env, k->ki_env,
144192239Sbrian			    VIS_TAB | VIS_NL | VIS_NOSLASH);
145192239Sbrian		} else
146192239Sbrian			vis_env = NULL;
147192239Sbrian
148225868Strasz		asprintf(&str, "%s%s%s%s",
149225868Strasz		    k->ki_d.prefix ? k->ki_d.prefix : "",
150225868Strasz		    vis_env ? vis_env : "",
151225868Strasz		    vis_env ? " " : "",
152225868Strasz		    vis_args);
153225868Strasz
154192239Sbrian		if (vis_env != NULL)
155192239Sbrian			free(vis_env);
156225868Strasz		free(vis_args);
157225868Strasz	} else {
158192239Sbrian		/* ki_d.prefix & ki_env aren't shown for interim fields */
159225868Strasz		str = vis_args;
160225868Strasz
161225868Strasz		if (strlen(str) > COMMAND_WIDTH)
162225868Strasz			str[COMMAND_WIDTH] = '\0';
163225868Strasz	}
164225868Strasz
165225868Strasz	return (str);
1661556Srgrimes}
1671556Srgrimes
168225868Straszchar *
16990110Simpucomm(KINFO *k, VARENT *ve)
1701556Srgrimes{
171225868Strasz	char *str;
1721556Srgrimes
173173004Sjulian	if (STAILQ_NEXT(ve, next_ve) == NULL) {	/* last field, don't pad */
174225868Strasz		asprintf(&str, "%s%s%s%s",
175225868Strasz		    k->ki_d.prefix ? k->ki_d.prefix : "",
176225868Strasz		    k->ki_p->ki_comm,
177225868Strasz		    (showthreads && k->ki_p->ki_numthreads > 1) ? "/" : "",
178225868Strasz		    (showthreads && k->ki_p->ki_numthreads > 1) ? k->ki_p->ki_tdname : "");
179189078Sattilio	} else {
180189078Sattilio		if (showthreads && k->ki_p->ki_numthreads > 1)
181225868Strasz			asprintf(&str, "%s/%s", k->ki_p->ki_comm, k->ki_p->ki_tdname);
182189078Sattilio		else
183225868Strasz			str = strdup(k->ki_p->ki_comm);
184189078Sattilio	}
185225868Strasz	return (str);
1861556Srgrimes}
1871556Srgrimes
188225868Straszchar *
189230287Sedtdnam(KINFO *k, VARENT *ve __unused)
190173004Sjulian{
191225868Strasz	char *str;
192173004Sjulian
193173004Sjulian	if (showthreads && k->ki_p->ki_numthreads > 1)
194225868Strasz		str = strdup(k->ki_p->ki_tdname);
195184925Semaste	else
196225868Strasz		str = strdup("      ");
197225868Strasz
198225868Strasz	return (str);
199173004Sjulian}
200173004Sjulian
201225868Straszchar *
202230287Sedlogname(KINFO *k, VARENT *ve __unused)
2031556Srgrimes{
2041556Srgrimes
205225868Strasz	if (*k->ki_p->ki_login == '\0')
206225868Strasz		return (NULL);
207225868Strasz	return (strdup(k->ki_p->ki_login));
2081556Srgrimes}
2091556Srgrimes
210225868Straszchar *
211230287Sedstate(KINFO *k, VARENT *ve __unused)
2121556Srgrimes{
213172207Sjeff	int flag, tdflags;
214225868Strasz	char *cp, *buf;
2151556Srgrimes
216225868Strasz	buf = malloc(16);
217225868Strasz	if (buf == NULL)
218225868Strasz		errx(1, "malloc failed");
219225868Strasz
22069896Smckusick	flag = k->ki_p->ki_flag;
22183366Sjulian	tdflags = k->ki_p->ki_tdflags;	/* XXXKSE */
2221556Srgrimes	cp = buf;
2231556Srgrimes
22469896Smckusick	switch (k->ki_p->ki_stat) {
2251556Srgrimes
2261556Srgrimes	case SSTOP:
2271556Srgrimes		*cp = 'T';
2281556Srgrimes		break;
2291556Srgrimes
2301556Srgrimes	case SSLEEP:
23183366Sjulian		if (tdflags & TDF_SINTR)	/* interruptable (long) */
23269896Smckusick			*cp = k->ki_p->ki_slptime >= MAXSLP ? 'I' : 'S';
2331556Srgrimes		else
2341556Srgrimes			*cp = 'D';
2351556Srgrimes		break;
2361556Srgrimes
2371556Srgrimes	case SRUN:
2381556Srgrimes	case SIDL:
2391556Srgrimes		*cp = 'R';
2401556Srgrimes		break;
2411556Srgrimes
24265557Sjasone	case SWAIT:
24365557Sjasone		*cp = 'W';
24465557Sjasone		break;
24565557Sjasone
246104388Sjhb	case SLOCK:
247104388Sjhb		*cp = 'L';
24865557Sjasone		break;
24965557Sjasone
2501556Srgrimes	case SZOMB:
2511556Srgrimes		*cp = 'Z';
2521556Srgrimes		break;
2531556Srgrimes
2541556Srgrimes	default:
2551556Srgrimes		*cp = '?';
2561556Srgrimes	}
2571556Srgrimes	cp++;
258172207Sjeff	if (!(flag & P_INMEM))
2591556Srgrimes		*cp++ = 'W';
26069896Smckusick	if (k->ki_p->ki_nice < NZERO)
2611556Srgrimes		*cp++ = '<';
26269896Smckusick	else if (k->ki_p->ki_nice > NZERO)
2631556Srgrimes		*cp++ = 'N';
2641556Srgrimes	if (flag & P_TRACED)
2651556Srgrimes		*cp++ = 'X';
26669896Smckusick	if (flag & P_WEXIT && k->ki_p->ki_stat != SZOMB)
2671556Srgrimes		*cp++ = 'E';
2681556Srgrimes	if (flag & P_PPWAIT)
2691556Srgrimes		*cp++ = 'V';
27069896Smckusick	if ((flag & P_SYSTEM) || k->ki_p->ki_lock > 0)
2711556Srgrimes		*cp++ = 'L';
27269896Smckusick	if (k->ki_p->ki_kiflag & KI_SLEADER)
2731556Srgrimes		*cp++ = 's';
27469896Smckusick	if ((flag & P_CONTROLT) && k->ki_p->ki_pgid == k->ki_p->ki_tpgid)
2751556Srgrimes		*cp++ = '+';
27646155Sphk	if (flag & P_JAILED)
27746155Sphk		*cp++ = 'J';
2781556Srgrimes	*cp = '\0';
279225868Strasz	return (buf);
2801556Srgrimes}
2811556Srgrimes
282130974Sgad#define	scalepri(x)	((x) - PZERO)
283130974Sgad
284225868Straszchar *
285230287Sedpri(KINFO *k, VARENT *ve __unused)
2861556Srgrimes{
287225868Strasz	char *str;
2881556Srgrimes
289225868Strasz	asprintf(&str, "%d", scalepri(k->ki_p->ki_pri.pri_level));
290225868Strasz	return (str);
2911556Srgrimes}
2921556Srgrimes
293225868Straszchar *
294230287Sedupr(KINFO *k, VARENT *ve __unused)
295130974Sgad{
296225868Strasz	char *str;
297130974Sgad
298225868Strasz	asprintf(&str, "%d", scalepri(k->ki_p->ki_pri.pri_user));
299225868Strasz	return (str);
300130974Sgad}
301130974Sgad#undef scalepri
302130974Sgad
303225868Straszchar *
304230287Seduname(KINFO *k, VARENT *ve __unused)
3051556Srgrimes{
3061556Srgrimes
307225868Strasz	return (strdup(user_from_uid(k->ki_p->ki_uid, 0)));
3081556Srgrimes}
3091556Srgrimes
310225868Straszchar *
311230287Sedegroupname(KINFO *k, VARENT *ve __unused)
312223086Strasz{
313223086Strasz
314225868Strasz	return (strdup(group_from_gid(k->ki_p->ki_groups[0], 0)));
315223086Strasz}
316223086Strasz
317225868Straszchar *
318230287Sedrgroupname(KINFO *k, VARENT *ve __unused)
31997961Sjmallett{
32097961Sjmallett
321225868Strasz	return (strdup(group_from_gid(k->ki_p->ki_rgid, 0)));
32297961Sjmallett}
32397961Sjmallett
324225868Straszchar *
325230287Sedruname(KINFO *k, VARENT *ve __unused)
3261556Srgrimes{
3271556Srgrimes
328225868Strasz	return (strdup(user_from_uid(k->ki_p->ki_ruid, 0)));
3291556Srgrimes}
3301556Srgrimes
331225868Straszchar *
332230287Sedtdev(KINFO *k, VARENT *ve __unused)
3331556Srgrimes{
3341556Srgrimes	dev_t dev;
335225868Strasz	char *str;
3361556Srgrimes
33769896Smckusick	dev = k->ki_p->ki_tdev;
3381556Srgrimes	if (dev == NODEV)
339226939Strasz		str = strdup("-");
340225847Sed	else
341225868Strasz		asprintf(&str, "%#jx", (uintmax_t)dev);
342225868Strasz
343225868Strasz	return (str);
3441556Srgrimes}
3451556Srgrimes
346225868Straszchar *
347230287Sedtname(KINFO *k, VARENT *ve __unused)
3481556Srgrimes{
3491556Srgrimes	dev_t dev;
350225868Strasz	char *ttname, *str;
3511556Srgrimes
35269896Smckusick	dev = k->ki_p->ki_tdev;
3531556Srgrimes	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
354226939Strasz		str = strdup("- ");
3551556Srgrimes	else {
3563301Sache		if (strncmp(ttname, "tty", 3) == 0 ||
3573301Sache		    strncmp(ttname, "cua", 3) == 0)
3581556Srgrimes			ttname += 3;
359155876Scognet		if (strncmp(ttname, "pts/", 4) == 0)
360155876Scognet			ttname += 4;
361225868Strasz		asprintf(&str, "%s%c", ttname,
362113485Scharnier		    k->ki_p->ki_kiflag & KI_CTTY ? ' ' : '-');
3631556Srgrimes	}
364225868Strasz
365225868Strasz	return (str);
3661556Srgrimes}
3671556Srgrimes
368225868Straszchar *
369230287Sedlongtname(KINFO *k, VARENT *ve __unused)
3701556Srgrimes{
3711556Srgrimes	dev_t dev;
372225868Strasz	const char *ttname;
3731556Srgrimes
37469896Smckusick	dev = k->ki_p->ki_tdev;
3751556Srgrimes	if (dev == NODEV || (ttname = devname(dev, S_IFCHR)) == NULL)
376226939Strasz		ttname = "-";
377225868Strasz
378225868Strasz	return (strdup(ttname));
3791556Srgrimes}
3801556Srgrimes
381225868Straszchar *
382230287Sedstarted(KINFO *k, VARENT *ve __unused)
3831556Srgrimes{
38437231Sbde	time_t then;
3851556Srgrimes	struct tm *tp;
386113485Scharnier	static int use_ampm = -1;
387225868Strasz	size_t buflen = 100;
388225868Strasz	char *buf;
3891556Srgrimes
390238488Sjilles	if (!k->ki_valid)
391238488Sjilles		return (NULL);
392238488Sjilles
393225868Strasz	buf = malloc(buflen);
394225868Strasz	if (buf == NULL)
395225868Strasz		errx(1, "malloc failed");
396225868Strasz
39773369Sache	if (use_ampm < 0)
39873369Sache		use_ampm = (*nl_langinfo(T_FMT_AMPM) != '\0');
39969896Smckusick	then = k->ki_p->ki_start.tv_sec;
40037231Sbde	tp = localtime(&then);
40169896Smckusick	if (now - k->ki_p->ki_start.tv_sec < 24 * 3600) {
402225868Strasz		(void)strftime(buf, buflen,
403113485Scharnier		    use_ampm ? "%l:%M%p" : "%k:%M  ", tp);
40469896Smckusick	} else if (now - k->ki_p->ki_start.tv_sec < 7 * 86400) {
405225868Strasz		(void)strftime(buf, buflen,
406113485Scharnier		    use_ampm ? "%a%I%p" : "%a%H  ", tp);
4071556Srgrimes	} else
408225868Strasz		(void)strftime(buf, buflen, "%e%b%y", tp);
409225868Strasz	return (buf);
4101556Srgrimes}
4111556Srgrimes
412225868Straszchar *
413230287Sedlstarted(KINFO *k, VARENT *ve __unused)
4141556Srgrimes{
41537231Sbde	time_t then;
416225868Strasz	char *buf;
417225868Strasz	size_t buflen = 100;
4181556Srgrimes
419238488Sjilles	if (!k->ki_valid)
420238488Sjilles		return (NULL);
421238488Sjilles
422225868Strasz	buf = malloc(buflen);
423225868Strasz	if (buf == NULL)
424225868Strasz		errx(1, "malloc failed");
425225868Strasz
42669896Smckusick	then = k->ki_p->ki_start.tv_sec;
427225868Strasz	(void)strftime(buf, buflen, "%c", localtime(&then));
428225868Strasz	return (buf);
4291556Srgrimes}
4301556Srgrimes
431225868Straszchar *
432230287Sedlockname(KINFO *k, VARENT *ve __unused)
43369372Sjhb{
434225868Strasz	char *str;
43569372Sjhb
436104388Sjhb	if (k->ki_p->ki_kiflag & KI_LOCKBLOCK) {
437104388Sjhb		if (k->ki_p->ki_lockname[0] != 0)
438225868Strasz			str = strdup(k->ki_p->ki_lockname);
43969372Sjhb		else
440225868Strasz			str = strdup("???");
44169372Sjhb	} else
442225868Strasz		str = NULL;
443225868Strasz
444225868Strasz	return (str);
44569372Sjhb}
44669372Sjhb
447225868Straszchar *
448230287Sedwchan(KINFO *k, VARENT *ve __unused)
4491556Srgrimes{
450225868Strasz	char *str;
4511556Srgrimes
45269896Smckusick	if (k->ki_p->ki_wchan) {
45369896Smckusick		if (k->ki_p->ki_wmesg[0] != 0)
454225868Strasz			str = strdup(k->ki_p->ki_wmesg);
4551556Srgrimes		else
456225868Strasz			asprintf(&str, "%lx", (long)k->ki_p->ki_wchan);
457113485Scharnier	} else
458225868Strasz		str = NULL;
459225868Strasz
460225868Strasz	return (str);
46191028Sdillon}
46291028Sdillon
463225868Straszchar *
464230287Sednwchan(KINFO *k, VARENT *ve __unused)
465118857Sharti{
466225868Strasz	char *str;
467118857Sharti
468225868Strasz	if (k->ki_p->ki_wchan)
469225868Strasz		asprintf(&str, "%0lx", (long)k->ki_p->ki_wchan);
470225868Strasz	else
471225868Strasz		str = NULL;
472225868Strasz
473225868Strasz	return (str);
474118857Sharti}
475118857Sharti
476225868Straszchar *
477230287Sedmwchan(KINFO *k, VARENT *ve __unused)
47891028Sdillon{
479225868Strasz	char *str;
48091028Sdillon
48191028Sdillon	if (k->ki_p->ki_wchan) {
48291028Sdillon		if (k->ki_p->ki_wmesg[0] != 0)
483225868Strasz			str = strdup(k->ki_p->ki_wmesg);
48491028Sdillon		else
485225868Strasz                        asprintf(&str, "%lx", (long)k->ki_p->ki_wchan);
486104388Sjhb	} else if (k->ki_p->ki_kiflag & KI_LOCKBLOCK) {
487104388Sjhb		if (k->ki_p->ki_lockname[0]) {
488225868Strasz			str = strdup(k->ki_p->ki_lockname);
489113485Scharnier		} else
490225868Strasz			str = strdup("???");
491113485Scharnier	} else
492225868Strasz		str = NULL;
493225868Strasz
494225868Strasz	return (str);
4951556Srgrimes}
4961556Srgrimes
497225868Straszchar *
498230287Sedvsize(KINFO *k, VARENT *ve __unused)
4991556Srgrimes{
500225868Strasz	char *str;
5011556Srgrimes
502225868Strasz	asprintf(&str, "%lu", (u_long)(k->ki_p->ki_size / 1024));
503225868Strasz	return (str);
5041556Srgrimes}
5051556Srgrimes
506225868Straszstatic char *
507230287Sedprinttime(KINFO *k, VARENT *ve __unused, long secs, long psecs)
508219713Skib/* psecs is "parts" of a second. first micro, then centi */
5091556Srgrimes{
510113485Scharnier	static char decimal_point;
511225868Strasz	char *str;
5121556Srgrimes
513113485Scharnier	if (decimal_point == '\0')
51472343Sache		decimal_point = localeconv()->decimal_point[0];
515130856Sgad	if (!k->ki_valid) {
51636497Sbde		secs = 0;
51736497Sbde		psecs = 0;
5181556Srgrimes	} else {
519219713Skib		/* round and scale to 100's */
52036497Sbde		psecs = (psecs + 5000) / 10000;
52136497Sbde		secs += psecs / 100;
52236497Sbde		psecs = psecs % 100;
5231556Srgrimes	}
524225868Strasz	asprintf(&str, "%ld:%02ld%c%02ld",
525113485Scharnier	    secs / 60, secs % 60, decimal_point, psecs);
526225868Strasz	return (str);
5271556Srgrimes}
5281556Srgrimes
529225868Straszchar *
530219713Skibcputime(KINFO *k, VARENT *ve)
531219713Skib{
532219713Skib	long secs, psecs;
533219713Skib
534219713Skib	/*
535219713Skib	 * This counts time spent handling interrupts.  We could
536219713Skib	 * fix this, but it is not 100% trivial (and interrupt
537219713Skib	 * time fractions only work on the sparc anyway).	XXX
538219713Skib	 */
539219713Skib	secs = k->ki_p->ki_runtime / 1000000;
540219713Skib	psecs = k->ki_p->ki_runtime % 1000000;
541219713Skib	if (sumrusage) {
542219713Skib		secs += k->ki_p->ki_childtime.tv_sec;
543219713Skib		psecs += k->ki_p->ki_childtime.tv_usec;
544219713Skib	}
545225868Strasz	return (printtime(k, ve, secs, psecs));
546219713Skib}
547219713Skib
548225868Straszchar *
549219713Skibsystime(KINFO *k, VARENT *ve)
550219713Skib{
551219713Skib	long secs, psecs;
552219713Skib
553219713Skib	secs = k->ki_p->ki_rusage.ru_stime.tv_sec;
554219713Skib	psecs = k->ki_p->ki_rusage.ru_stime.tv_usec;
555219713Skib	if (sumrusage) {
556219713Skib		secs += k->ki_p->ki_childstime.tv_sec;
557219713Skib		psecs += k->ki_p->ki_childstime.tv_usec;
558219713Skib	}
559225868Strasz	return (printtime(k, ve, secs, psecs));
560219713Skib}
561219713Skib
562225868Straszchar *
563219713Skibusertime(KINFO *k, VARENT *ve)
564219713Skib{
565219713Skib	long secs, psecs;
566219713Skib
567219713Skib	secs = k->ki_p->ki_rusage.ru_utime.tv_sec;
568219713Skib	psecs = k->ki_p->ki_rusage.ru_utime.tv_usec;
569219713Skib	if (sumrusage) {
570219713Skib		secs += k->ki_p->ki_childutime.tv_sec;
571219713Skib		psecs += k->ki_p->ki_childutime.tv_usec;
572219713Skib	}
573225868Strasz	return (printtime(k, ve, secs, psecs));
574219713Skib}
575219713Skib
576225868Straszchar *
577230287Sedelapsed(KINFO *k, VARENT *ve __unused)
57897965Sjmallett{
579113485Scharnier	time_t val;
580113485Scharnier	int days, hours, mins, secs;
581225868Strasz	char *str;
58297965Sjmallett
583225868Strasz	if (!k->ki_valid)
584225868Strasz		return (NULL);
585113485Scharnier	val = now - k->ki_p->ki_start.tv_sec;
586113485Scharnier	days = val / (24 * 60 * 60);
587113485Scharnier	val %= 24 * 60 * 60;
588113485Scharnier	hours = val / (60 * 60);
589113485Scharnier	val %= 60 * 60;
590113485Scharnier	mins = val / 60;
591113485Scharnier	secs = val % 60;
592113485Scharnier	if (days != 0)
593225868Strasz		asprintf(&str, "%3d-%02d:%02d:%02d", days, hours, mins, secs);
594113485Scharnier	else if (hours != 0)
595225868Strasz		asprintf(&str, "%02d:%02d:%02d", hours, mins, secs);
596113485Scharnier	else
597225868Strasz		asprintf(&str, "%02d:%02d", mins, secs);
598225868Strasz
599225868Strasz	return (str);
60097965Sjmallett}
60197965Sjmallett
602225868Straszchar *
603230287Sedelapseds(KINFO *k, VARENT *ve __unused)
604205271Sjmallett{
605205271Sjmallett	time_t val;
606225868Strasz	char *str;
607205271Sjmallett
608225868Strasz	if (!k->ki_valid)
609225868Strasz		return (NULL);
610205271Sjmallett	val = now - k->ki_p->ki_start.tv_sec;
611225868Strasz	asprintf(&str, "%jd", (intmax_t)val);
612225868Strasz	return (str);
613205271Sjmallett}
614205271Sjmallett
6151556Srgrimesdouble
61690143Smarkmgetpcpu(const KINFO *k)
6171556Srgrimes{
6181556Srgrimes	static int failure;
6191556Srgrimes
6201556Srgrimes	if (!nlistread)
6211556Srgrimes		failure = donlist();
6221556Srgrimes	if (failure)
6231556Srgrimes		return (0.0);
6241556Srgrimes
6251556Srgrimes#define	fxtofl(fixpt)	((double)(fixpt) / fscale)
6261556Srgrimes
6271556Srgrimes	/* XXX - I don't like this */
628172207Sjeff	if (k->ki_p->ki_swtime == 0 || (k->ki_p->ki_flag & P_INMEM) == 0)
6291556Srgrimes		return (0.0);
6301556Srgrimes	if (rawcpu)
63169896Smckusick		return (100.0 * fxtofl(k->ki_p->ki_pctcpu));
63269896Smckusick	return (100.0 * fxtofl(k->ki_p->ki_pctcpu) /
63369896Smckusick		(1.0 - exp(k->ki_p->ki_swtime * log(fxtofl(ccpu)))));
6341556Srgrimes}
6351556Srgrimes
636225868Straszchar *
637230287Sedpcpu(KINFO *k, VARENT *ve __unused)
6381556Srgrimes{
639225868Strasz	char *str;
6401556Srgrimes
641225868Strasz	asprintf(&str, "%.1f", getpcpu(k));
642225868Strasz	return (str);
6431556Srgrimes}
6441556Srgrimes
64590143Smarkmstatic double
64690110Simpgetpmem(KINFO *k)
6471556Srgrimes{
6481556Srgrimes	static int failure;
6491556Srgrimes	double fracmem;
6501556Srgrimes
6511556Srgrimes	if (!nlistread)
6521556Srgrimes		failure = donlist();
6531556Srgrimes	if (failure)
6541556Srgrimes		return (0.0);
6551556Srgrimes
656172207Sjeff	if ((k->ki_p->ki_flag & P_INMEM) == 0)
6571556Srgrimes		return (0.0);
6581556Srgrimes	/* XXX want pmap ptpages, segtab, etc. (per architecture) */
6591556Srgrimes	/* XXX don't have info about shared */
660113485Scharnier	fracmem = ((float)k->ki_p->ki_rssize) / mempages;
6611556Srgrimes	return (100.0 * fracmem);
6621556Srgrimes}
6631556Srgrimes
664225868Straszchar *
665230287Sedpmem(KINFO *k, VARENT *ve __unused)
6661556Srgrimes{
667225868Strasz	char *str;
6681556Srgrimes
669225868Strasz	asprintf(&str, "%.1f", getpmem(k));
670225868Strasz	return (str);
6711556Srgrimes}
6721556Srgrimes
673225868Straszchar *
674230287Sedpagein(KINFO *k, VARENT *ve __unused)
6751556Srgrimes{
676225868Strasz	char *str;
6771556Srgrimes
678225868Strasz	asprintf(&str, "%ld", k->ki_valid ? k->ki_p->ki_rusage.ru_majflt : 0);
679225868Strasz	return (str);
6801556Srgrimes}
6811556Srgrimes
68290143Smarkm/* ARGSUSED */
683225868Straszchar *
684230287Sedmaxrss(KINFO *k __unused, VARENT *ve __unused)
6851556Srgrimes{
6861556Srgrimes
68727856Speter	/* XXX not yet */
688225868Strasz	return (NULL);
6891556Srgrimes}
6901556Srgrimes
691225868Straszchar *
692230287Sedpriorityr(KINFO *k, VARENT *ve __unused)
69336352Ssteve{
69490143Smarkm	struct priority *lpri;
695225868Strasz	char *str;
69672377Sjake	unsigned class, level;
697127512Sgad
698127512Sgad	lpri = &k->ki_p->ki_pri;
69990143Smarkm	class = lpri->pri_class;
70090143Smarkm	level = lpri->pri_level;
70172377Sjake	switch (class) {
702131215Sgad	case PRI_ITHD:
703225868Strasz		asprintf(&str, "intr:%u", level);
704131215Sgad		break;
70572377Sjake	case PRI_REALTIME:
706225868Strasz		asprintf(&str, "real:%u", level);
70736352Ssteve		break;
70872377Sjake	case PRI_TIMESHARE:
709225868Strasz		asprintf(&str, "normal");
71036352Ssteve		break;
71172377Sjake	case PRI_IDLE:
712225868Strasz		asprintf(&str, "idle:%u", level);
71336352Ssteve		break;
71436352Ssteve	default:
715225868Strasz		asprintf(&str, "%u:%u", class, level);
71636352Ssteve		break;
71736352Ssteve	}
718225868Strasz	return (str);
71936352Ssteve}
72036352Ssteve
7211556Srgrimes/*
7221556Srgrimes * Generic output routines.  Print fields from various prototype
7231556Srgrimes * structures.
7241556Srgrimes */
725225868Straszstatic char *
72699547Sjmallettprintval(void *bp, VAR *v)
7271556Srgrimes{
7281556Srgrimes	static char ofmt[32] = "%";
72997843Sjmallett	const char *fcp;
730225868Strasz	char *cp, *str;
7311556Srgrimes
7321556Srgrimes	cp = ofmt + 1;
7331556Srgrimes	fcp = v->fmt;
7347165Sjoerg	while ((*cp++ = *fcp++));
7351556Srgrimes
736113395Stjr#define	CHKINF127(n)	(((n) > 127) && (v->flag & INF127) ? 127 : (n))
737113395Stjr
7381556Srgrimes	switch (v->type) {
7391556Srgrimes	case CHAR:
740225868Strasz		(void)asprintf(&str, ofmt, *(char *)bp);
7411556Srgrimes		break;
7421556Srgrimes	case UCHAR:
743225868Strasz		(void)asprintf(&str, ofmt, *(u_char *)bp);
7441556Srgrimes		break;
7451556Srgrimes	case SHORT:
746225868Strasz		(void)asprintf(&str, ofmt, *(short *)bp);
7471556Srgrimes		break;
7481556Srgrimes	case USHORT:
749225868Strasz		(void)asprintf(&str, ofmt, *(u_short *)bp);
7501556Srgrimes		break;
75139160Sdfr	case INT:
752225868Strasz		(void)asprintf(&str, ofmt, *(int *)bp);
75339160Sdfr		break;
75439160Sdfr	case UINT:
755225868Strasz		(void)asprintf(&str, ofmt, CHKINF127(*(u_int *)bp));
75639160Sdfr		break;
7571556Srgrimes	case LONG:
758225868Strasz		(void)asprintf(&str, ofmt, *(long *)bp);
7591556Srgrimes		break;
7601556Srgrimes	case ULONG:
761225868Strasz		(void)asprintf(&str, ofmt, *(u_long *)bp);
7621556Srgrimes		break;
7631556Srgrimes	case KPTR:
764225868Strasz		(void)asprintf(&str, ofmt, *(u_long *)bp);
7651556Srgrimes		break;
766103497Sjmallett	case PGTOK:
767225868Strasz		(void)asprintf(&str, ofmt, ps_pgtok(*(u_long *)bp));
768103438Sjmallett		break;
7691556Srgrimes	default:
7701556Srgrimes		errx(1, "unknown type %d", v->type);
7711556Srgrimes	}
772225868Strasz
773225868Strasz	return (str);
7741556Srgrimes}
7751556Srgrimes
776225868Straszchar *
77790110Simpkvar(KINFO *k, VARENT *ve)
7781556Srgrimes{
7791556Srgrimes	VAR *v;
7801556Srgrimes
7811556Srgrimes	v = ve->var;
782225868Strasz	return (printval((char *)((char *)k->ki_p + v->off), v));
7831556Srgrimes}
7841556Srgrimes
785225868Straszchar *
78690110Simprvar(KINFO *k, VARENT *ve)
7871556Srgrimes{
7881556Srgrimes	VAR *v;
7891556Srgrimes
7901556Srgrimes	v = ve->var;
791225868Strasz	if (!k->ki_valid)
792225868Strasz		return (NULL);
793225868Strasz	return (printval((char *)((char *)(&k->ki_p->ki_rusage) + v->off), v));
7941556Srgrimes}
79586922Sgreen
796225868Straszchar *
797230287Sedemulname(KINFO *k, VARENT *ve __unused)
798130830Sgad{
799130830Sgad
800225868Strasz	return (strdup(k->ki_p->ki_emul));
801130830Sgad}
802130830Sgad
803225868Straszchar *
804230287Sedlabel(KINFO *k, VARENT *ve __unused)
80586922Sgreen{
806105831Srwatson	char *string;
807109460Sjmallett	mac_t proclabel;
808105831Srwatson	int error;
80986922Sgreen
810105831Srwatson	string = NULL;
811109460Sjmallett	if (mac_prepare_process_label(&proclabel) == -1) {
812132433Stjr		warn("mac_prepare_process_label");
813105831Srwatson		goto out;
814105831Srwatson	}
815109460Sjmallett	error = mac_get_pid(k->ki_p->ki_pid, proclabel);
816105831Srwatson	if (error == 0) {
817109460Sjmallett		if (mac_to_text(proclabel, &string) == -1)
818105831Srwatson			string = NULL;
819105831Srwatson	}
820109460Sjmallett	mac_free(proclabel);
821105831Srwatsonout:
822225868Strasz	return (string);
82386922Sgreen}
824105831Srwatson
825225868Straszchar *
826230287Sedloginclass(KINFO *k, VARENT *ve __unused)
827219307Strasz{
828219307Strasz
829219307Strasz	/*
830219307Strasz	 * Don't display login class for system processes;
831219307Strasz	 * login classes are used for resource limits,
832219307Strasz	 * and limits don't apply to system processes.
833219307Strasz	 */
834219307Strasz	if (k->ki_p->ki_flag & P_SYSTEM) {
835225868Strasz		return (strdup("-"));
836219307Strasz	}
837260195Strasz	return (strdup(k->ki_p->ki_loginclass));
838219967Strasz}
839