Home | History | Annotate | Line # | Download | only in systat
ps.c revision 1.17
      1  1.17   simonb /*      $NetBSD: ps.c,v 1.17 2000/12/01 02:19:44 simonb 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.17   simonb __RCSID("$NetBSD: ps.c,v 1.17 2000/12/01 02:19:44 simonb 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.1    jwise #include "extern.h"
     65   1.1    jwise #include "systat.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.16       ad char *state2str(struct kinfo_proc *);
     70  1.16       ad char *tty2str(struct kinfo_proc *);
     71  1.16       ad int rss2int(struct kinfo_proc *);
     72  1.16       ad int vsz2int(struct kinfo_proc *);
     73  1.16       ad char *comm2str(struct kinfo_proc *);
     74  1.16       ad double pmem2float(struct kinfo_proc *);
     75  1.16       ad char *start2str(struct kinfo_proc *);
     76  1.16       ad char *time2str(struct kinfo_proc *);
     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.1    jwise 	const char *user, *comm, *state, *tty, *start, *time;
     98   1.1    jwise 	pid_t pid;
     99   1.3    itohy 	double pctcpu, pctmem;
    100   1.1    jwise 	struct  eproc *ep;
    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.1    jwise 		ep = &pt[k].pt_kp->kp_eproc;
    115  1.12   kleink 		if (showuser != SHOWUSER_ANY && ep->e_ucred.cr_uid != showuser)
    116  1.12   kleink 			continue;
    117   1.1    jwise 		user = user_from_uid(ep->e_ucred.cr_uid, 0);
    118   1.1    jwise 		pid = pt[k].pt_kp->kp_proc.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.1    jwise 		time = 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.12   kleink 		    user, pid, pctcpu, pctmem, vsz, rss, tty, state, start, time, comm);
    135  1.12   kleink 		i--;
    136   1.1    jwise 	}
    137  1.12   kleink 	wmove(wnd, y, 0);
    138  1.12   kleink 	wclrtobot(wnd);
    139   1.1    jwise }
    140   1.1    jwise 
    141   1.1    jwise int
    142  1.16       ad compare_pctcpu_noidle(const void *a, const void *b)
    143   1.1    jwise {
    144   1.1    jwise 	if (((struct p_times *) a)->pt_kp == NULL)
    145   1.1    jwise 		return 1;
    146   1.1    jwise 
    147   1.1    jwise 	if (((struct p_times *) b)->pt_kp == NULL)
    148   1.1    jwise 	 	return -1;
    149   1.1    jwise 
    150   1.1    jwise 	return (((struct p_times *) a)->pt_pctcpu >
    151   1.1    jwise 		((struct p_times *) b)->pt_pctcpu)? -1: 1;
    152   1.1    jwise }
    153   1.1    jwise 
    154   1.1    jwise /* from here down adapted from .../src/usr.bin/ps/print.c .  Any mistakes are my own, however. */
    155   1.1    jwise char *
    156  1.16       ad state2str(struct kinfo_proc *kp)
    157   1.1    jwise {
    158   1.1    jwise 	struct proc *p;
    159   1.1    jwise 	struct eproc *e;
    160   1.1    jwise 	int flag;
    161   1.1    jwise 	char *cp;
    162   1.1    jwise 	char buf[5];
    163   1.1    jwise 	static char statestr[4];
    164   1.1    jwise 
    165   1.1    jwise 	p = &(kp->kp_proc);
    166   1.1    jwise 	e = &(kp->kp_eproc);
    167   1.1    jwise 
    168   1.1    jwise 	flag = p->p_flag;
    169   1.1    jwise 	cp = buf;
    170   1.1    jwise 
    171   1.1    jwise 	switch (p->p_stat) {
    172   1.1    jwise 	case SSTOP:
    173   1.1    jwise 		*cp = 'T';
    174   1.1    jwise 		break;
    175   1.1    jwise 
    176   1.1    jwise 	case SSLEEP:
    177   1.1    jwise 		if (flag & P_SINTR)     /* interuptable (long) */
    178   1.1    jwise 			*cp = p->p_slptime >= MAXSLP ? 'I' : 'S';
    179   1.1    jwise 		else
    180   1.1    jwise 			*cp = 'D';
    181   1.1    jwise 		break;
    182   1.1    jwise 
    183   1.1    jwise 	case SRUN:
    184   1.1    jwise 	case SIDL:
    185  1.14  thorpej 	case SONPROC:
    186   1.1    jwise 		*cp = 'R';
    187   1.1    jwise 		break;
    188   1.1    jwise 
    189   1.1    jwise 	case SZOMB:
    190  1.13   itojun #ifdef SDEAD
    191   1.5    veego 	case SDEAD:
    192  1.13   itojun #endif
    193   1.1    jwise 		*cp = 'Z';
    194   1.1    jwise 		break;
    195   1.1    jwise 
    196   1.1    jwise 	default:
    197   1.1    jwise 		*cp = '?';
    198   1.1    jwise 	}
    199   1.1    jwise 	cp++;
    200   1.1    jwise 	if (flag & P_INMEM) {
    201   1.1    jwise 	} else
    202   1.1    jwise 		*cp++ = 'W';
    203   1.1    jwise 	if (p->p_nice < NZERO)
    204   1.1    jwise 		*cp++ = '<';
    205   1.1    jwise 	else if (p->p_nice > NZERO)
    206   1.1    jwise 		*cp++ = 'N';
    207   1.1    jwise 	if (flag & P_TRACED)
    208   1.1    jwise 		*cp++ = 'X';
    209   1.4  thorpej 	if (flag & P_WEXIT && P_ZOMBIE(p) == 0)
    210   1.1    jwise 		*cp++ = 'E';
    211   1.1    jwise 	if (flag & P_PPWAIT)
    212   1.1    jwise 		*cp++ = 'V';
    213   1.1    jwise 	if ((flag & P_SYSTEM) || p->p_holdcnt)
    214   1.1    jwise 		*cp++ = 'L';
    215   1.1    jwise 	if (e->e_flag & EPROC_SLEADER)
    216   1.1    jwise 		*cp++ = 's';
    217   1.1    jwise 	if ((flag & P_CONTROLT) && e->e_pgid == e->e_tpgid)
    218   1.1    jwise 		*cp++ = '+';
    219   1.1    jwise 	*cp = '\0';
    220  1.10    jwise 	snprintf(statestr, sizeof(statestr), "%-s",  buf);
    221   1.1    jwise 
    222   1.1    jwise 	return statestr;
    223   1.1    jwise }
    224   1.1    jwise 
    225   1.1    jwise char *
    226  1.16       ad tty2str(struct kinfo_proc *kp)
    227   1.1    jwise {
    228   1.1    jwise 	static char ttystr[4];
    229   1.1    jwise 	char *ttyname;
    230   1.1    jwise 	struct eproc *e;
    231   1.1    jwise 
    232   1.1    jwise 	e = &(kp->kp_eproc);
    233   1.1    jwise 
    234   1.1    jwise 	if (e->e_tdev == NODEV || (ttyname = devname(e->e_tdev, S_IFCHR)) == NULL)
    235   1.1    jwise 		strcpy(ttystr, "??");
    236   1.1    jwise 	else {
    237   1.6      mrg 		if (strncmp(ttyname, "tty", 3) == 0 ||
    238   1.6      mrg 		    strncmp(ttyname, "dty", 3) == 0)
    239   1.1    jwise 			ttyname += 3;
    240  1.10    jwise 		snprintf(ttystr, sizeof(ttystr), "%s%c", ttyname, e->e_flag & EPROC_CTTY ? ' ' : '-');
    241   1.1    jwise 	}
    242   1.1    jwise 
    243   1.1    jwise 	return ttystr;
    244   1.1    jwise }
    245   1.1    jwise 
    246   1.1    jwise #define pgtok(a)	(((a)*getpagesize())/1024)
    247   1.1    jwise 
    248   1.1    jwise int
    249  1.16       ad vsz2int(struct kinfo_proc *kp)
    250   1.1    jwise {
    251   1.1    jwise 	struct eproc *e;
    252   1.1    jwise 	int     i;
    253   1.1    jwise 
    254   1.1    jwise 	e = &(kp->kp_eproc);
    255   1.1    jwise 	i = pgtok(e->e_vm.vm_dsize + e->e_vm.vm_ssize + e->e_vm.vm_tsize);
    256   1.1    jwise 
    257   1.1    jwise 	return ((i < 0) ? 0 : i);
    258   1.1    jwise }
    259   1.1    jwise 
    260   1.1    jwise int
    261  1.16       ad rss2int(struct kinfo_proc *kp)
    262   1.1    jwise {
    263   1.1    jwise 	struct eproc *e;
    264   1.1    jwise 	int	i;
    265   1.1    jwise 
    266   1.1    jwise 	e = &(kp->kp_eproc);
    267   1.1    jwise 	i = pgtok(e->e_vm.vm_rssize);
    268   1.1    jwise 
    269   1.1    jwise 	/* XXX don't have info about shared */
    270   1.1    jwise 	return ((i < 0) ? 0 : i);
    271   1.1    jwise }
    272   1.1    jwise 
    273   1.1    jwise char *
    274  1.16       ad comm2str(struct kinfo_proc *kp)
    275   1.1    jwise {
    276   1.1    jwise 	char **argv, **pt;
    277   1.1    jwise 	static char commstr[41];
    278   1.1    jwise 	struct proc *p;
    279   1.1    jwise 
    280   1.1    jwise 	p = &(kp->kp_proc);
    281   1.1    jwise 	commstr[0]='\0';
    282   1.1    jwise 
    283   1.1    jwise 	argv = kvm_getargv(kd, kp, 40);
    284   1.1    jwise 	if ((pt = argv) != NULL) {
    285   1.1    jwise 		while (*pt) {
    286   1.1    jwise 			strcat(commstr, *pt);
    287   1.1    jwise 			pt++;
    288   1.1    jwise 			strcat(commstr, " ");
    289   1.1    jwise 		}
    290   1.1    jwise 	} else {
    291   1.1    jwise 		commstr[0] = '(';
    292   1.1    jwise 		commstr[1] = '\0';
    293   1.1    jwise 		strncat(commstr, p->p_comm, sizeof(commstr) - 1);
    294   1.1    jwise 		strcat(commstr, ")");
    295   1.1    jwise 	}
    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.16       ad pmem2float(struct kinfo_proc *kp)
    302   1.1    jwise {
    303   1.1    jwise 	struct proc *p;
    304   1.1    jwise 	struct eproc *e;
    305   1.1    jwise 	double fracmem;
    306   1.1    jwise 	int szptudot;
    307   1.1    jwise 
    308   1.1    jwise 	p = &(kp->kp_proc);
    309   1.1    jwise 	e = &(kp->kp_eproc);
    310   1.1    jwise 
    311   1.1    jwise 	if ((p->p_flag & P_INMEM) == 0)
    312   1.1    jwise 	        return (0.0);
    313   1.1    jwise 	/* XXX want pmap ptpages, segtab, etc. (per architecture) */
    314   1.1    jwise 	szptudot = USPACE/getpagesize();
    315   1.1    jwise 	/* XXX don't have info about shared */
    316   1.7    fredb 	fracmem = ((double)e->e_vm.vm_rssize + szptudot)/mempages;
    317   1.1    jwise 	return (fracmem >= 0) ? 100.0 * fracmem : 0;
    318   1.1    jwise }
    319   1.1    jwise 
    320   1.1    jwise char *
    321  1.16       ad start2str(struct kinfo_proc *kp)
    322   1.1    jwise {
    323   1.1    jwise 	struct proc *p;
    324   1.1    jwise 	struct pstats pstats;
    325   1.1    jwise 	struct timeval u_start;
    326   1.1    jwise 	struct tm *tp;
    327   1.1    jwise 	time_t startt;
    328   1.1    jwise 	static char startstr[10];
    329   1.1    jwise 
    330   1.1    jwise 	p = &(kp->kp_proc);
    331   1.1    jwise 
    332   1.1    jwise 	kvm_read(kd, (u_long)&(p->p_addr->u_stats), (char *)&pstats, sizeof(pstats));
    333   1.1    jwise 	u_start = pstats.p_start;
    334   1.1    jwise 
    335   1.1    jwise 	startt = u_start.tv_sec;
    336   1.1    jwise 	tp = localtime(&startt);
    337   1.1    jwise 	if (now == 0)
    338   1.1    jwise 	        time(&now);
    339   1.1    jwise 	if (now - u_start.tv_sec < 24 * SECSPERHOUR) {
    340   1.1    jwise 		/* I *hate* SCCS... */
    341   1.1    jwise 	        static char fmt[] = __CONCAT("%l:%", "M%p");
    342   1.1    jwise 	        strftime(startstr, sizeof(startstr) - 1, fmt, tp);
    343   1.1    jwise 	} else if (now - u_start.tv_sec < 7 * SECSPERDAY) {
    344   1.1    jwise 	        /* I *hate* SCCS... */
    345   1.1    jwise 	        static char fmt[] = __CONCAT("%a%", "I%p");
    346   1.1    jwise 	        strftime(startstr, sizeof(startstr) - 1, fmt, tp);
    347   1.1    jwise 	} else
    348   1.1    jwise 	        strftime(startstr, sizeof(startstr) - 1, "%e%b%y", tp);
    349   1.1    jwise 
    350   1.1    jwise 	return startstr;
    351   1.1    jwise }
    352   1.1    jwise 
    353   1.1    jwise char *
    354  1.16       ad time2str(struct kinfo_proc *kp)
    355   1.1    jwise {
    356   1.1    jwise 	long secs;
    357   1.1    jwise 	long psecs;     /* "parts" of a second. first micro, then centi */
    358   1.1    jwise 	static char timestr[10];
    359   1.1    jwise 	struct proc *p;
    360   1.1    jwise 
    361   1.1    jwise 	p = &(kp->kp_proc);
    362   1.1    jwise 
    363   1.4  thorpej 	if (P_ZOMBIE(p)) {
    364   1.1    jwise 	        secs = 0;
    365   1.1    jwise 	        psecs = 0;
    366   1.1    jwise 	} else {
    367   1.1    jwise 	        /*
    368   1.1    jwise 	         * This counts time spent handling interrupts.  We could
    369   1.1    jwise 	         * fix this, but it is not 100% trivial (and interrupt
    370   1.1    jwise 	         * time fractions only work on the sparc anyway).       XXX
    371   1.1    jwise 	         */
    372   1.1    jwise 	        secs = p->p_rtime.tv_sec;
    373   1.1    jwise 	        psecs = p->p_rtime.tv_usec;
    374   1.1    jwise 	        /* if (sumrusage) {
    375   1.1    jwise 	                secs += k->ki_u.u_cru.ru_utime.tv_sec +
    376   1.1    jwise 	                        k->ki_u.u_cru.ru_stime.tv_sec;
    377   1.1    jwise 	                psecs += k->ki_u.u_cru.ru_utime.tv_usec +
    378   1.1    jwise 	                        k->ki_u.u_cru.ru_stime.tv_usec;
    379   1.1    jwise 	        } */
    380   1.1    jwise 	        /*
    381   1.1    jwise 	         * round and scale to 100's
    382   1.1    jwise 	         */
    383   1.1    jwise 	        psecs = (psecs + 5000) / 10000;
    384   1.1    jwise 	        secs += psecs / 100;
    385   1.1    jwise 	        psecs = psecs % 100;
    386   1.1    jwise 	}
    387   1.1    jwise 	snprintf(timestr, sizeof(timestr), "%3ld:%02ld.%02ld", secs/60, 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.12   kleink 	if (args == NULL)
    398  1.12   kleink 		args = "";
    399  1.12   kleink 	if (strcmp(args, "+") == 0) {
    400  1.12   kleink 		uid = SHOWUSER_ANY;
    401  1.12   kleink 	} else if (uid_from_user(args, &uid) != 0) {
    402  1.12   kleink 		error("%s: unknown user", args);
    403  1.12   kleink 		return;
    404  1.12   kleink 	}
    405  1.12   kleink 
    406  1.12   kleink 	showuser = uid;
    407  1.12   kleink 	display(0);
    408   1.1    jwise }
    409