Home | History | Annotate | Line # | Download | only in systat
      1  1.40      maya /*      $NetBSD: ps.c,v 1.40 2021/04/17 08:34:27 maya Exp $  */
      2   1.1     jwise 
      3   1.1     jwise /*-
      4   1.1     jwise  * Copyright (c) 1999
      5   1.1     jwise  *      The NetBSD Foundation, Inc.  All rights reserved.
      6   1.1     jwise  *
      7   1.1     jwise  * Redistribution and use in source and binary forms, with or without
      8   1.1     jwise  * modification, are permitted provided that the following conditions
      9   1.1     jwise  * are met:
     10   1.1     jwise  * 1. Redistributions of source code must retain the above copyright
     11   1.1     jwise  *    notice, this list of conditions and the following disclaimer.
     12   1.1     jwise  * 2. Redistributions in binary form must reproduce the above copyright
     13   1.1     jwise  *    notice, this list of conditions and the following disclaimer in the
     14   1.1     jwise  *    documentation and/or other materials provided with the distribution.
     15   1.9     jwise  * 3. All advertising materials mentioning features or use of this software
     16   1.9     jwise  *    must display the following acknowledgement:
     17  1.11     jwise  *      This product includes software developed by the NetBSD Foundation.
     18  1.11     jwise  * 4. Neither the name of the Foundation nor the names of its contributors
     19   1.1     jwise  *    may be used to endorse or promote products derived from this software
     20   1.1     jwise  *    without specific prior written permission.
     21   1.1     jwise  *
     22   1.1     jwise  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     23   1.1     jwise  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     24   1.1     jwise  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     25   1.1     jwise  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     26   1.1     jwise  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     27   1.1     jwise  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     28   1.1     jwise  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     29   1.1     jwise  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     30   1.1     jwise  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     31   1.1     jwise  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     32   1.1     jwise  * SUCH DAMAGE.
     33   1.1     jwise  */
     34   1.1     jwise 
     35   1.1     jwise /*
     36   1.1     jwise  * XXX Notes XXX
     37   1.1     jwise  * showps -- print data needed at each refresh
     38   1.1     jwise  * fetchps -- get data used by mode (done at each refresh)
     39   1.1     jwise  * labelps -- print labels (ie info not needing refreshing)
     40   1.1     jwise  * initps -- prepare once-only data structures for mode
     41   1.1     jwise  * openps -- prepare per-run information for mode, return window
     42   1.1     jwise  * closeps -- close mode to prepare to switch modes
     43   1.1     jwise  * cmdps -- optional, handle commands
     44   1.1     jwise  */
     45   1.2    simonb 
     46   1.2    simonb #include <sys/cdefs.h>
     47   1.2    simonb #ifndef lint
     48  1.40      maya __RCSID("$NetBSD: ps.c,v 1.40 2021/04/17 08:34:27 maya Exp $");
     49   1.2    simonb #endif /* not lint */
     50   1.1     jwise 
     51   1.1     jwise #include <sys/param.h>
     52  1.15     perry #include <sys/sched.h>
     53   1.1     jwise #include <sys/sysctl.h>
     54  1.37  christos #include <sys/stat.h>
     55  1.17    simonb 
     56   1.1     jwise #include <curses.h>
     57   1.1     jwise #include <math.h>
     58   1.1     jwise #include <pwd.h>
     59   1.1     jwise #include <stdlib.h>
     60   1.1     jwise #include <string.h>
     61   1.1     jwise #include <tzfile.h>
     62   1.1     jwise #include <unistd.h>
     63   1.1     jwise 
     64  1.27      matt #include "systat.h"
     65   1.1     jwise #include "extern.h"
     66   1.1     jwise #include "ps.h"
     67   1.1     jwise 
     68  1.16        ad int compare_pctcpu_noidle(const void *, const void *);
     69  1.20   thorpej char *state2str(struct kinfo_proc2 *);
     70  1.20   thorpej char *tty2str(struct kinfo_proc2 *);
     71  1.20   thorpej int rss2int(struct kinfo_proc2 *);
     72  1.20   thorpej int vsz2int(struct kinfo_proc2 *);
     73  1.20   thorpej char *comm2str(struct kinfo_proc2 *);
     74  1.20   thorpej double pmem2float(struct kinfo_proc2 *);
     75  1.20   thorpej char *start2str(struct kinfo_proc2 *);
     76  1.20   thorpej char *time2str(struct kinfo_proc2 *);
     77   1.1     jwise 
     78   1.1     jwise static time_t now;
     79   1.1     jwise 
     80  1.12    kleink #define SHOWUSER_ANY	(uid_t)-1
     81  1.12    kleink static uid_t showuser = SHOWUSER_ANY;
     82  1.12    kleink 
     83  1.13    itojun #ifndef P_ZOMBIE
     84  1.13    itojun #define P_ZOMBIE(p)	((p)->p_stat == SZOMB)
     85  1.13    itojun #endif
     86  1.13    itojun 
     87   1.1     jwise void
     88  1.16        ad labelps(void)
     89   1.1     jwise {
     90   1.1     jwise 	mvwaddstr(wnd, 0, 0, "USER      PID %CPU %MEM    VSZ   RSS TT  STAT STARTED       TIME COMMAND");
     91   1.1     jwise }
     92   1.1     jwise 
     93   1.1     jwise void
     94  1.16        ad showps(void)
     95   1.1     jwise {
     96   1.1     jwise 	int i, k, y, vsz, rss;
     97  1.26       dsl 	const char *user, *comm, *state, *tty, *start, *time_str;
     98   1.1     jwise 	pid_t pid;
     99   1.3     itohy 	double pctcpu, pctmem;
    100  1.20   thorpej 	struct kinfo_proc2 *kp;
    101   1.1     jwise 
    102   1.1     jwise 	now = 0;	/* force start2str to reget current time */
    103   1.1     jwise 
    104   1.1     jwise 	qsort(pt, nproc + 1, sizeof (struct p_times), compare_pctcpu_noidle);
    105   1.1     jwise 
    106   1.1     jwise 	y = 1;
    107   1.1     jwise 	i = nproc + 1;
    108   1.1     jwise 	if (i > getmaxy(wnd)-2)
    109   1.1     jwise 		i = getmaxy(wnd)-1;
    110  1.12    kleink 	for (k = 0; i > 0 ; k++) {
    111   1.1     jwise 		if (pt[k].pt_kp == NULL) /* We're all the way down to the imaginary idle proc */
    112  1.12    kleink 			break;
    113   1.1     jwise 
    114  1.20   thorpej 		kp = pt[k].pt_kp;
    115  1.20   thorpej 		if (showuser != SHOWUSER_ANY && kp->p_uid != showuser)
    116  1.12    kleink 			continue;
    117  1.20   thorpej 		user = user_from_uid(kp->p_uid, 0);
    118  1.20   thorpej 		pid = kp->p_pid;
    119   1.3     itohy 		pctcpu = 100.0 * pt[k].pt_pctcpu;
    120   1.1     jwise 		pctmem = pmem2float(pt[k].pt_kp);
    121   1.1     jwise 		vsz = vsz2int(pt[k].pt_kp);
    122   1.1     jwise 		rss = rss2int(pt[k].pt_kp);
    123   1.1     jwise 		tty = tty2str(pt[k].pt_kp);
    124   1.1     jwise 		state = state2str(pt[k].pt_kp);
    125   1.1     jwise 		start = start2str(pt[k].pt_kp);
    126  1.26       dsl 		time_str = time2str(pt[k].pt_kp);
    127   1.1     jwise 		comm = comm2str(pt[k].pt_kp);
    128   1.1     jwise 		/*comm = pt[k].pt_kp->kp_proc.p_comm; */
    129   1.1     jwise 
    130   1.1     jwise 		wmove(wnd, y, 0);
    131   1.1     jwise 		wclrtoeol(wnd);
    132  1.12    kleink 		mvwprintw(wnd, y++, 0,
    133  1.12    kleink 		    "%-8.8s%5d %4.1f %4.1f %6d %5d %-3s %-4s %7s %10.10s %s",
    134  1.26       dsl 		    user, pid, pctcpu, pctmem, vsz, rss, tty, state, start,
    135  1.26       dsl 		    time_str, comm);
    136  1.12    kleink 		i--;
    137   1.1     jwise 	}
    138  1.12    kleink 	wmove(wnd, y, 0);
    139  1.12    kleink 	wclrtobot(wnd);
    140   1.1     jwise }
    141   1.1     jwise 
    142   1.1     jwise int
    143  1.16        ad compare_pctcpu_noidle(const void *a, const void *b)
    144   1.1     jwise {
    145  1.26       dsl 	if (((const struct p_times *) a)->pt_kp == NULL)
    146   1.1     jwise 		return 1;
    147   1.1     jwise 
    148  1.26       dsl 	if (((const struct p_times *) b)->pt_kp == NULL)
    149   1.1     jwise 	 	return -1;
    150   1.1     jwise 
    151  1.26       dsl 	return (((const struct p_times *) a)->pt_pctcpu >
    152  1.26       dsl 		((const struct p_times *) b)->pt_pctcpu)? -1: 1;
    153   1.1     jwise }
    154   1.1     jwise 
    155   1.1     jwise /* from here down adapted from .../src/usr.bin/ps/print.c .  Any mistakes are my own, however. */
    156   1.1     jwise char *
    157  1.20   thorpej state2str(struct kinfo_proc2 *kp)
    158   1.1     jwise {
    159   1.1     jwise 	int flag;
    160   1.1     jwise 	char *cp;
    161   1.1     jwise 	char buf[5];
    162   1.1     jwise 	static char statestr[4];
    163   1.1     jwise 
    164  1.20   thorpej 	flag = kp->p_flag;
    165   1.1     jwise 	cp = buf;
    166   1.1     jwise 
    167  1.20   thorpej 	switch (kp->p_stat) {
    168  1.22   thorpej 	case LSSTOP:
    169   1.1     jwise 		*cp = 'T';
    170   1.1     jwise 		break;
    171   1.1     jwise 
    172  1.22   thorpej 	case LSSLEEP:
    173  1.22   thorpej 		if (flag & L_SINTR)     /* interruptable (long) */
    174  1.33     lukem 			*cp = kp->p_slptime >= (uint32_t)maxslp ? 'I' : 'S';
    175   1.1     jwise 		else
    176   1.1     jwise 			*cp = 'D';
    177   1.1     jwise 		break;
    178   1.1     jwise 
    179  1.22   thorpej 	case LSRUN:
    180  1.22   thorpej 	case LSIDL:
    181  1.22   thorpej 	case LSONPROC:
    182   1.1     jwise 		*cp = 'R';
    183   1.1     jwise 		break;
    184   1.1     jwise 
    185  1.22   thorpej 	case LSZOMB:
    186  1.22   thorpej #ifdef LSDEAD
    187  1.22   thorpej 	case LSDEAD:
    188  1.13    itojun #endif
    189   1.1     jwise 		*cp = 'Z';
    190   1.1     jwise 		break;
    191   1.1     jwise 
    192   1.1     jwise 	default:
    193   1.1     jwise 		*cp = '?';
    194   1.1     jwise 	}
    195   1.1     jwise 	cp++;
    196  1.20   thorpej 	if (kp->p_nice < NZERO)
    197   1.1     jwise 		*cp++ = '<';
    198  1.20   thorpej 	else if (kp->p_nice > NZERO)
    199   1.1     jwise 		*cp++ = 'N';
    200  1.30     pavel 	if (flag & P_TRACED)
    201   1.1     jwise 		*cp++ = 'X';
    202  1.30     pavel 	if (flag & P_WEXIT &&
    203  1.20   thorpej 	    /* XXX - I don't like this */
    204  1.29        ad 	    (kp->p_stat != LSZOMB))
    205   1.1     jwise 		*cp++ = 'E';
    206  1.30     pavel 	if (flag & P_PPWAIT)
    207   1.1     jwise 		*cp++ = 'V';
    208  1.20   thorpej 	if (kp->p_eflag & EPROC_SLEADER)
    209   1.1     jwise 		*cp++ = 's';
    210  1.30     pavel 	if ((flag & P_CONTROLT) && kp->p__pgid == kp->p_tpgid)
    211   1.1     jwise 		*cp++ = '+';
    212   1.1     jwise 	*cp = '\0';
    213  1.10     jwise 	snprintf(statestr, sizeof(statestr), "%-s",  buf);
    214   1.1     jwise 
    215   1.1     jwise 	return statestr;
    216   1.1     jwise }
    217   1.1     jwise 
    218   1.1     jwise char *
    219  1.20   thorpej tty2str(struct kinfo_proc2 *kp)
    220   1.1     jwise {
    221   1.1     jwise 	static char ttystr[4];
    222  1.26       dsl 	char *tty_name;
    223   1.1     jwise 
    224  1.31  christos 	if (kp->p_tdev == (uint32_t)NODEV ||
    225  1.26       dsl 	    (tty_name = devname(kp->p_tdev, S_IFCHR)) == NULL)
    226  1.23    itojun 		strlcpy(ttystr, "??", sizeof(ttystr));
    227   1.1     jwise 	else {
    228  1.26       dsl 		if (strncmp(tty_name, "tty", 3) == 0 ||
    229  1.26       dsl 		    strncmp(tty_name, "dty", 3) == 0)
    230  1.26       dsl 			tty_name += 3;
    231  1.26       dsl 		snprintf(ttystr, sizeof(ttystr), "%s%c", tty_name,
    232  1.20   thorpej 		    kp->p_eflag & EPROC_CTTY ? ' ' : '-');
    233   1.1     jwise 	}
    234   1.1     jwise 
    235   1.1     jwise 	return ttystr;
    236   1.1     jwise }
    237   1.1     jwise 
    238   1.1     jwise #define pgtok(a)	(((a)*getpagesize())/1024)
    239   1.1     jwise 
    240   1.1     jwise int
    241  1.20   thorpej vsz2int(struct kinfo_proc2 *kp)
    242   1.1     jwise {
    243   1.1     jwise 	int     i;
    244   1.1     jwise 
    245  1.32       mrg 	i = pgtok(kp->p_vm_msize);
    246   1.1     jwise 
    247   1.1     jwise 	return ((i < 0) ? 0 : i);
    248  1.20   thorpej }
    249   1.1     jwise 
    250   1.1     jwise int
    251  1.20   thorpej rss2int(struct kinfo_proc2 *kp)
    252   1.1     jwise {
    253   1.1     jwise 	int	i;
    254   1.1     jwise 
    255  1.20   thorpej 	i = pgtok(kp->p_vm_rssize);
    256   1.1     jwise 
    257   1.1     jwise 	/* XXX don't have info about shared */
    258   1.1     jwise 	return ((i < 0) ? 0 : i);
    259   1.1     jwise }
    260   1.1     jwise 
    261   1.1     jwise char *
    262  1.20   thorpej comm2str(struct kinfo_proc2 *kp)
    263   1.1     jwise {
    264  1.26       dsl 	char **argv;
    265   1.1     jwise 	static char commstr[41];
    266   1.1     jwise 
    267   1.1     jwise 	commstr[0]='\0';
    268   1.1     jwise 
    269  1.20   thorpej 	argv = kvm_getargv2(kd, kp, 40);
    270  1.26       dsl 	if (argv != NULL) {
    271  1.26       dsl 		while (*argv) {
    272  1.26       dsl 			strlcat(commstr, *argv, sizeof(commstr));
    273  1.26       dsl 			argv++;
    274  1.24    itojun 			strlcat(commstr, " ", sizeof(commstr));
    275   1.1     jwise 		}
    276  1.28    kleink 	} else {
    277  1.28    kleink 		const char *fmt;
    278  1.28    kleink 
    279  1.28    kleink 		/*
    280  1.28    kleink 		 * Commands that don't set an argv vector are printed with
    281  1.28    kleink 		 * square brackets if they are system commands.  Otherwise
    282  1.28    kleink 		 * they are printed within parentheses.
    283  1.28    kleink 		 */
    284  1.30     pavel 		if (kp->p_flag & P_SYSTEM)
    285  1.35  christos 			fmt = "[]";
    286  1.28    kleink 		else
    287  1.35  christos 			fmt = "()";
    288  1.28    kleink 
    289  1.35  christos 		snprintf(commstr, sizeof(commstr), "%c%s%c", fmt[0],
    290  1.35  christos 		    kp->p_comm, fmt[1]);
    291  1.28    kleink 	}
    292   1.1     jwise 
    293   1.1     jwise 	return commstr;
    294   1.1     jwise }
    295   1.1     jwise 
    296   1.3     itohy double
    297  1.20   thorpej pmem2float(struct kinfo_proc2 *kp)
    298   1.1     jwise {
    299   1.1     jwise 	double fracmem;
    300  1.39    simonb 	static int szptudot = -1;
    301  1.39    simonb 
    302  1.39    simonb 	/*
    303  1.39    simonb 	 * XXX want pmap ptpages, segtab, etc. (per architecture),
    304  1.39    simonb 	 * not just the uarea.
    305  1.39    simonb 	 */
    306  1.39    simonb 	if (szptudot < 0) {
    307  1.39    simonb 		int mib[2];
    308  1.39    simonb 		size_t size;
    309  1.39    simonb 		int uspace;
    310  1.39    simonb 
    311  1.39    simonb 		mib[0] = CTL_VM;
    312  1.39    simonb 		mib[1] = VM_USPACE;
    313  1.39    simonb 		size = sizeof(uspace);
    314  1.39    simonb 		if (sysctl(mib, 2, &uspace, &size, NULL, 0) == 0) {
    315  1.39    simonb 			szptudot = uspace / getpagesize();
    316  1.39    simonb 		} else {
    317  1.39    simonb 			/* pick a vaguely useful default */
    318  1.39    simonb 			szptudot = getpagesize();
    319  1.39    simonb 		}
    320  1.39    simonb 	}
    321   1.1     jwise 
    322   1.1     jwise 	/* XXX don't have info about shared */
    323  1.39    simonb 	fracmem = ((double)kp->p_vm_rssize + szptudot) / mempages;
    324   1.1     jwise 	return (fracmem >= 0) ? 100.0 * fracmem : 0;
    325   1.1     jwise }
    326   1.1     jwise 
    327   1.1     jwise char *
    328  1.20   thorpej start2str(struct kinfo_proc2 *kp)
    329   1.1     jwise {
    330   1.1     jwise 	struct timeval u_start;
    331   1.1     jwise 	struct tm *tp;
    332   1.1     jwise 	time_t startt;
    333   1.1     jwise 	static char startstr[10];
    334   1.1     jwise 
    335  1.20   thorpej 	u_start.tv_sec = kp->p_ustart_sec;
    336  1.20   thorpej 	u_start.tv_usec = kp->p_ustart_usec;
    337   1.1     jwise 
    338   1.1     jwise 	startt = u_start.tv_sec;
    339   1.1     jwise 	tp = localtime(&startt);
    340   1.1     jwise 	if (now == 0)
    341   1.1     jwise 	        time(&now);
    342   1.1     jwise 	if (now - u_start.tv_sec < 24 * SECSPERHOUR) {
    343  1.40      maya 	        strftime(startstr, sizeof(startstr) - 1, "%l:%M%p", tp);
    344   1.1     jwise 	} else if (now - u_start.tv_sec < 7 * SECSPERDAY) {
    345  1.40      maya 	        strftime(startstr, sizeof(startstr) - 1, "%a%I%p", tp);
    346   1.1     jwise 	} else
    347   1.1     jwise 	        strftime(startstr, sizeof(startstr) - 1, "%e%b%y", tp);
    348   1.1     jwise 
    349   1.1     jwise 	return startstr;
    350   1.1     jwise }
    351   1.1     jwise 
    352   1.1     jwise char *
    353  1.20   thorpej time2str(struct kinfo_proc2 *kp)
    354   1.1     jwise {
    355   1.1     jwise 	long secs;
    356   1.1     jwise 	long psecs;     /* "parts" of a second. first micro, then centi */
    357  1.38       mrg 	static char timestr[18];
    358   1.1     jwise 
    359  1.20   thorpej 	/* XXX - I don't like this. */
    360  1.25  jdolecek 	if (kp->p_stat == SZOMB) {
    361   1.1     jwise 	        secs = 0;
    362   1.1     jwise 	        psecs = 0;
    363   1.1     jwise 	} else {
    364   1.1     jwise 	        /*
    365   1.1     jwise 	         * This counts time spent handling interrupts.  We could
    366   1.1     jwise 	         * fix this, but it is not 100% trivial (and interrupt
    367   1.1     jwise 	         * time fractions only work on the sparc anyway).       XXX
    368   1.1     jwise 	         */
    369  1.20   thorpej 	        secs = kp->p_rtime_sec;
    370  1.20   thorpej 	        psecs = kp->p_rtime_usec;
    371  1.20   thorpej #if 0
    372  1.20   thorpej 	        if (sumrusage) {
    373   1.1     jwise 	                secs += k->ki_u.u_cru.ru_utime.tv_sec +
    374   1.1     jwise 	                        k->ki_u.u_cru.ru_stime.tv_sec;
    375   1.1     jwise 	                psecs += k->ki_u.u_cru.ru_utime.tv_usec +
    376   1.1     jwise 	                        k->ki_u.u_cru.ru_stime.tv_usec;
    377  1.20   thorpej 	        }
    378  1.20   thorpej #endif
    379   1.1     jwise 	        /*
    380   1.1     jwise 	         * round and scale to 100's
    381   1.1     jwise 	         */
    382   1.1     jwise 	        psecs = (psecs + 5000) / 10000;
    383   1.1     jwise 	        secs += psecs / 100;
    384   1.1     jwise 	        psecs = psecs % 100;
    385   1.1     jwise 	}
    386  1.20   thorpej 	snprintf(timestr, sizeof(timestr), "%3ld:%02ld.%02ld", secs/60,
    387  1.20   thorpej 	    secs%60, psecs);
    388   1.1     jwise 
    389   1.1     jwise 	return timestr;
    390  1.12    kleink }
    391  1.12    kleink 
    392  1.12    kleink void
    393  1.16        ad ps_user(char *args)
    394  1.12    kleink {
    395  1.12    kleink 	uid_t uid;
    396  1.12    kleink 
    397  1.26       dsl 	if (args == NULL || *args == 0 || strcmp(args, "+") == 0) {
    398  1.12    kleink 		uid = SHOWUSER_ANY;
    399  1.12    kleink 	} else if (uid_from_user(args, &uid) != 0) {
    400  1.12    kleink 		error("%s: unknown user", args);
    401  1.12    kleink 		return;
    402  1.12    kleink 	}
    403  1.12    kleink 
    404  1.12    kleink 	showuser = uid;
    405  1.12    kleink 	display(0);
    406   1.1     jwise }
    407