Home | History | Annotate | Line # | Download | only in systat
ps.c revision 1.32
      1  1.32       mrg /*      $NetBSD: ps.c,v 1.32 2009/03/29 01:02:51 mrg 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.32       mrg __RCSID("$NetBSD: ps.c,v 1.32 2009/03/29 01:02:51 mrg 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.1     jwise #include <sys/user.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.20   thorpej 			*cp = kp->p_slptime >= 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.22   thorpej 	if (flag & L_INMEM) {
    197   1.1     jwise 	} else
    198   1.1     jwise 		*cp++ = 'W';
    199  1.20   thorpej 	if (kp->p_nice < NZERO)
    200   1.1     jwise 		*cp++ = '<';
    201  1.20   thorpej 	else if (kp->p_nice > NZERO)
    202   1.1     jwise 		*cp++ = 'N';
    203  1.30     pavel 	if (flag & P_TRACED)
    204   1.1     jwise 		*cp++ = 'X';
    205  1.30     pavel 	if (flag & P_WEXIT &&
    206  1.20   thorpej 	    /* XXX - I don't like this */
    207  1.29        ad 	    (kp->p_stat != LSZOMB))
    208   1.1     jwise 		*cp++ = 'E';
    209  1.30     pavel 	if (flag & P_PPWAIT)
    210   1.1     jwise 		*cp++ = 'V';
    211  1.30     pavel 	if ((flag & P_SYSTEM) || kp->p_holdcnt)
    212   1.1     jwise 		*cp++ = 'L';
    213  1.20   thorpej 	if (kp->p_eflag & EPROC_SLEADER)
    214   1.1     jwise 		*cp++ = 's';
    215  1.30     pavel 	if ((flag & P_CONTROLT) && kp->p__pgid == kp->p_tpgid)
    216   1.1     jwise 		*cp++ = '+';
    217   1.1     jwise 	*cp = '\0';
    218  1.10     jwise 	snprintf(statestr, sizeof(statestr), "%-s",  buf);
    219   1.1     jwise 
    220   1.1     jwise 	return statestr;
    221   1.1     jwise }
    222   1.1     jwise 
    223   1.1     jwise char *
    224  1.20   thorpej tty2str(struct kinfo_proc2 *kp)
    225   1.1     jwise {
    226   1.1     jwise 	static char ttystr[4];
    227  1.26       dsl 	char *tty_name;
    228   1.1     jwise 
    229  1.31  christos 	if (kp->p_tdev == (uint32_t)NODEV ||
    230  1.26       dsl 	    (tty_name = devname(kp->p_tdev, S_IFCHR)) == NULL)
    231  1.23    itojun 		strlcpy(ttystr, "??", sizeof(ttystr));
    232   1.1     jwise 	else {
    233  1.26       dsl 		if (strncmp(tty_name, "tty", 3) == 0 ||
    234  1.26       dsl 		    strncmp(tty_name, "dty", 3) == 0)
    235  1.26       dsl 			tty_name += 3;
    236  1.26       dsl 		snprintf(ttystr, sizeof(ttystr), "%s%c", tty_name,
    237  1.20   thorpej 		    kp->p_eflag & EPROC_CTTY ? ' ' : '-');
    238   1.1     jwise 	}
    239   1.1     jwise 
    240   1.1     jwise 	return ttystr;
    241   1.1     jwise }
    242   1.1     jwise 
    243   1.1     jwise #define pgtok(a)	(((a)*getpagesize())/1024)
    244   1.1     jwise 
    245   1.1     jwise int
    246  1.20   thorpej vsz2int(struct kinfo_proc2 *kp)
    247   1.1     jwise {
    248   1.1     jwise 	int     i;
    249   1.1     jwise 
    250  1.32       mrg 	i = pgtok(kp->p_vm_msize);
    251   1.1     jwise 
    252   1.1     jwise 	return ((i < 0) ? 0 : i);
    253  1.20   thorpej }
    254   1.1     jwise 
    255   1.1     jwise int
    256  1.20   thorpej rss2int(struct kinfo_proc2 *kp)
    257   1.1     jwise {
    258   1.1     jwise 	int	i;
    259   1.1     jwise 
    260  1.20   thorpej 	i = pgtok(kp->p_vm_rssize);
    261   1.1     jwise 
    262   1.1     jwise 	/* XXX don't have info about shared */
    263   1.1     jwise 	return ((i < 0) ? 0 : i);
    264   1.1     jwise }
    265   1.1     jwise 
    266   1.1     jwise char *
    267  1.20   thorpej comm2str(struct kinfo_proc2 *kp)
    268   1.1     jwise {
    269  1.26       dsl 	char **argv;
    270   1.1     jwise 	static char commstr[41];
    271   1.1     jwise 
    272   1.1     jwise 	commstr[0]='\0';
    273   1.1     jwise 
    274  1.20   thorpej 	argv = kvm_getargv2(kd, kp, 40);
    275  1.26       dsl 	if (argv != NULL) {
    276  1.26       dsl 		while (*argv) {
    277  1.26       dsl 			strlcat(commstr, *argv, sizeof(commstr));
    278  1.26       dsl 			argv++;
    279  1.24    itojun 			strlcat(commstr, " ", sizeof(commstr));
    280   1.1     jwise 		}
    281  1.28    kleink 	} else {
    282  1.28    kleink 		const char *fmt;
    283  1.28    kleink 
    284  1.28    kleink 		/*
    285  1.28    kleink 		 * Commands that don't set an argv vector are printed with
    286  1.28    kleink 		 * square brackets if they are system commands.  Otherwise
    287  1.28    kleink 		 * they are printed within parentheses.
    288  1.28    kleink 		 */
    289  1.30     pavel 		if (kp->p_flag & P_SYSTEM)
    290  1.28    kleink 			fmt = "[%s]";
    291  1.28    kleink 		else
    292  1.28    kleink 			fmt = "(%s)";
    293  1.28    kleink 
    294  1.28    kleink 		snprintf(commstr, sizeof(commstr), fmt, kp->p_comm);
    295  1.28    kleink 	}
    296   1.1     jwise 
    297   1.1     jwise 	return commstr;
    298   1.1     jwise }
    299   1.1     jwise 
    300   1.3     itohy double
    301  1.20   thorpej pmem2float(struct kinfo_proc2 *kp)
    302   1.1     jwise {
    303   1.1     jwise 	double fracmem;
    304  1.19      matt 	int szptudot = 0;
    305   1.1     jwise 
    306  1.20   thorpej 	/* XXX - I don't like this. */
    307  1.22   thorpej 	if ((kp->p_flag & L_INMEM) == 0)
    308   1.1     jwise 	        return (0.0);
    309  1.19      matt #ifdef USPACE
    310   1.1     jwise 	/* XXX want pmap ptpages, segtab, etc. (per architecture) */
    311   1.1     jwise 	szptudot = USPACE/getpagesize();
    312  1.19      matt #endif
    313   1.1     jwise 	/* XXX don't have info about shared */
    314  1.20   thorpej 	fracmem = ((double)kp->p_vm_rssize + szptudot)/mempages;
    315   1.1     jwise 	return (fracmem >= 0) ? 100.0 * fracmem : 0;
    316   1.1     jwise }
    317   1.1     jwise 
    318   1.1     jwise char *
    319  1.20   thorpej start2str(struct kinfo_proc2 *kp)
    320   1.1     jwise {
    321   1.1     jwise 	struct timeval u_start;
    322   1.1     jwise 	struct tm *tp;
    323   1.1     jwise 	time_t startt;
    324   1.1     jwise 	static char startstr[10];
    325   1.1     jwise 
    326  1.20   thorpej 	u_start.tv_sec = kp->p_ustart_sec;
    327  1.20   thorpej 	u_start.tv_usec = kp->p_ustart_usec;
    328   1.1     jwise 
    329   1.1     jwise 	startt = u_start.tv_sec;
    330   1.1     jwise 	tp = localtime(&startt);
    331   1.1     jwise 	if (now == 0)
    332   1.1     jwise 	        time(&now);
    333   1.1     jwise 	if (now - u_start.tv_sec < 24 * SECSPERHOUR) {
    334   1.1     jwise 		/* I *hate* SCCS... */
    335  1.18       cgd 	        static char fmt[] = "%l:%" "M%p";
    336   1.1     jwise 	        strftime(startstr, sizeof(startstr) - 1, fmt, tp);
    337   1.1     jwise 	} else if (now - u_start.tv_sec < 7 * SECSPERDAY) {
    338   1.1     jwise 	        /* I *hate* SCCS... */
    339  1.18       cgd 	        static char fmt[] = "%a%" "I%p";
    340   1.1     jwise 	        strftime(startstr, sizeof(startstr) - 1, fmt, tp);
    341   1.1     jwise 	} else
    342   1.1     jwise 	        strftime(startstr, sizeof(startstr) - 1, "%e%b%y", tp);
    343   1.1     jwise 
    344   1.1     jwise 	return startstr;
    345   1.1     jwise }
    346   1.1     jwise 
    347   1.1     jwise char *
    348  1.20   thorpej time2str(struct kinfo_proc2 *kp)
    349   1.1     jwise {
    350   1.1     jwise 	long secs;
    351   1.1     jwise 	long psecs;     /* "parts" of a second. first micro, then centi */
    352   1.1     jwise 	static char timestr[10];
    353   1.1     jwise 
    354  1.20   thorpej 	/* XXX - I don't like this. */
    355  1.25  jdolecek 	if (kp->p_stat == SZOMB) {
    356   1.1     jwise 	        secs = 0;
    357   1.1     jwise 	        psecs = 0;
    358   1.1     jwise 	} else {
    359   1.1     jwise 	        /*
    360   1.1     jwise 	         * This counts time spent handling interrupts.  We could
    361   1.1     jwise 	         * fix this, but it is not 100% trivial (and interrupt
    362   1.1     jwise 	         * time fractions only work on the sparc anyway).       XXX
    363   1.1     jwise 	         */
    364  1.20   thorpej 	        secs = kp->p_rtime_sec;
    365  1.20   thorpej 	        psecs = kp->p_rtime_usec;
    366  1.20   thorpej #if 0
    367  1.20   thorpej 	        if (sumrusage) {
    368   1.1     jwise 	                secs += k->ki_u.u_cru.ru_utime.tv_sec +
    369   1.1     jwise 	                        k->ki_u.u_cru.ru_stime.tv_sec;
    370   1.1     jwise 	                psecs += k->ki_u.u_cru.ru_utime.tv_usec +
    371   1.1     jwise 	                        k->ki_u.u_cru.ru_stime.tv_usec;
    372  1.20   thorpej 	        }
    373  1.20   thorpej #endif
    374   1.1     jwise 	        /*
    375   1.1     jwise 	         * round and scale to 100's
    376   1.1     jwise 	         */
    377   1.1     jwise 	        psecs = (psecs + 5000) / 10000;
    378   1.1     jwise 	        secs += psecs / 100;
    379   1.1     jwise 	        psecs = psecs % 100;
    380   1.1     jwise 	}
    381  1.20   thorpej 	snprintf(timestr, sizeof(timestr), "%3ld:%02ld.%02ld", secs/60,
    382  1.20   thorpej 	    secs%60, psecs);
    383   1.1     jwise 
    384   1.1     jwise 	return timestr;
    385  1.12    kleink }
    386  1.12    kleink 
    387  1.12    kleink void
    388  1.16        ad ps_user(char *args)
    389  1.12    kleink {
    390  1.12    kleink 	uid_t uid;
    391  1.12    kleink 
    392  1.26       dsl 	if (args == NULL || *args == 0 || strcmp(args, "+") == 0) {
    393  1.12    kleink 		uid = SHOWUSER_ANY;
    394  1.12    kleink 	} else if (uid_from_user(args, &uid) != 0) {
    395  1.12    kleink 		error("%s: unknown user", args);
    396  1.12    kleink 		return;
    397  1.12    kleink 	}
    398  1.12    kleink 
    399  1.12    kleink 	showuser = uid;
    400  1.12    kleink 	display(0);
    401   1.1     jwise }
    402