159243Sobrien/*
259243Sobrien * sh.time.c: Shell time keeping and printing.
359243Sobrien */
459243Sobrien/*-
559243Sobrien * Copyright (c) 1980, 1991 The	Regents	of the University of California.
659243Sobrien * All rights reserved.
759243Sobrien *
859243Sobrien * Redistribution and use in source and	binary forms, with or without
959243Sobrien * modification, are permitted provided	that the following conditions
1059243Sobrien * are met:
1159243Sobrien * 1. Redistributions of source	code must retain the above copyright
1259243Sobrien *    notice, this list	of conditions and the following	disclaimer.
1359243Sobrien * 2. Redistributions in binary	form must reproduce the	above copyright
1459243Sobrien *    notice, this list	of conditions and the following	disclaimer in the
1559243Sobrien *    documentation and/or other materials provided with the distribution.
16100616Smp * 3. Neither the name of the University nor the names of its contributors
1759243Sobrien *    may be used to endorse or	promote	products derived from this software
1859243Sobrien *    without specific prior written permission.
1959243Sobrien *
2059243Sobrien * THIS	SOFTWARE IS PROVIDED BY	THE REGENTS AND	CONTRIBUTORS ``AS IS'' AND
2159243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2259243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2359243Sobrien * ARE DISCLAIMED.  IN NO EVENT	SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2459243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR	CONSEQUENTIAL
2559243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2659243Sobrien * OR SERVICES;	LOSS OF	USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2759243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2859243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2959243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3059243Sobrien * SUCH	DAMAGE.
3159243Sobrien */
3259243Sobrien#include "sh.h"
3359243Sobrien#ifdef SUNOS4
3459243Sobrien# include <machine/param.h>
3559243Sobrien#endif /* SUNOS4 */
3659243Sobrien
3759243Sobrien/*
3859243Sobrien * C Shell - routines handling process timing and niceing
3959243Sobrien */
4059243Sobrien#ifdef BSDTIMES
4159243Sobrien# ifndef RUSAGE_SELF
4259243Sobrien#  define	RUSAGE_SELF	0
4359243Sobrien#  define	RUSAGE_CHILDREN	-1
4459243Sobrien# endif	/* RUSAGE_SELF */
4559243Sobrien#else /* BSDTIMES */
4659243Sobrienstruct tms times0;
4759243Sobrien#endif /* BSDTIMES */
4859243Sobrien
4959243Sobrien#if !defined(BSDTIMES) && !defined(_SEQUENT_)
5059243Sobrien# ifdef	POSIX
51167465Smpstatic	void	pdtimet	(clock_t, clock_t);
5259243Sobrien# else /* ! POSIX */
53167465Smpstatic	void	pdtimet	(time_t, time_t);
5459243Sobrien# endif	/* ! POSIX */
5559243Sobrien#else /* BSDTIMES || _SEQUENT_ */
56167465Smpstatic	void	tvadd	(timeval_t *, timeval_t *);
57167465Smpstatic	void	pdeltat	(timeval_t *, timeval_t *);
5859243Sobrien#endif /* BSDTIMES || _SEQUENT_	*/
5959243Sobrien
6059243Sobrienvoid
61167465Smpsettimes(void)
6259243Sobrien{
6359243Sobrien#ifdef BSDTIMES
6459243Sobrien    struct sysrusage ruch;
6559243Sobrien#ifdef convex
6659243Sobrien    memset(&ru0, 0, sizeof(ru0));
6759243Sobrien    memset(&ruch, 0, sizeof(ruch));
6859243Sobrien#endif /* convex */
6959243Sobrien
7059243Sobrien    (void) gettimeofday(&time0,	NULL);
7159243Sobrien    (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru0);
7259243Sobrien    (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
7359243Sobrien    ruadd(&ru0,	&ruch);
7459243Sobrien#else
7559243Sobrien# ifdef	_SEQUENT_
7659243Sobrien    struct process_stats ruch;
7759243Sobrien
7859243Sobrien    (void) get_process_stats(&time0, PS_SELF, &ru0, &ruch);
7959243Sobrien    ruadd(&ru0,	&ruch);
8059243Sobrien# else	/* _SEQUENT_ */
8159415Sobrien    seconds0 = time(NULL);
8259243Sobrien    time0 = times(&times0);
8359243Sobrien    times0.tms_stime +=	times0.tms_cstime;
8459243Sobrien    times0.tms_utime +=	times0.tms_cutime;
8559243Sobrien    times0.tms_cstime =	0;
8659243Sobrien    times0.tms_cutime =	0;
8759243Sobrien# endif	/* _SEQUENT_ */
8859243Sobrien#endif /* BSDTIMES */
8959243Sobrien}
9059243Sobrien
9159243Sobrien/*
9259243Sobrien * dotime is only called if it is truly	a builtin function and not a
9359243Sobrien * prefix to another command
9459243Sobrien */
9559243Sobrien/*ARGSUSED*/
9659243Sobrienvoid
97167465Smpdotime(Char **v, struct command *c)
9859243Sobrien{
9959243Sobrien#ifdef BSDTIMES
10059243Sobrien    timeval_t timedol;
10159243Sobrien    struct sysrusage ru1, ruch;
10259243Sobrien#ifdef convex
10359243Sobrien    memset(&ru1, 0, sizeof(ru1));
10459243Sobrien    memset(&ruch, 0, sizeof(ruch));
10559243Sobrien#endif /* convex */
10659243Sobrien
10759243Sobrien    (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru1);
10859243Sobrien    (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
10959243Sobrien    ruadd(&ru1,	&ruch);
11059243Sobrien    (void) gettimeofday(&timedol, NULL);
11159243Sobrien    prusage(&ru0, &ru1,	&timedol, &time0);
11259243Sobrien#else
11359243Sobrien# ifdef	_SEQUENT_
11459243Sobrien    timeval_t timedol;
11559243Sobrien    struct process_stats ru1, ruch;
11659243Sobrien
11759243Sobrien    (void) get_process_stats(&timedol, PS_SELF,	&ru1, &ruch);
11859243Sobrien    ruadd(&ru1,	&ruch);
11959243Sobrien    prusage(&ru0, &ru1,	&timedol, &time0);
12059243Sobrien# else /* _SEQUENT_ */
12159243Sobrien#  ifndef POSIX
12259243Sobrien    time_t  timedol;
12359243Sobrien#  else	/* POSIX */
12459243Sobrien    clock_t timedol;
12559243Sobrien#  endif /* POSIX */
12659243Sobrien
12759243Sobrien    struct tms times_dol;
12859243Sobrien
12959243Sobrien    timedol = times(&times_dol);
13059243Sobrien    times_dol.tms_stime	+= times_dol.tms_cstime;
13159243Sobrien    times_dol.tms_utime	+= times_dol.tms_cutime;
13259243Sobrien    times_dol.tms_cstime = 0;
13359243Sobrien    times_dol.tms_cutime = 0;
13459243Sobrien    prusage(&times0, &times_dol, timedol, time0);
13559243Sobrien# endif	/* _SEQUENT_ */
13659243Sobrien#endif /* BSDTIMES */
13759243Sobrien    USE(c);
13859243Sobrien    USE(v);
13959243Sobrien}
14059243Sobrien
14159243Sobrien/*
14259243Sobrien * donice is only called when it on the	line by	itself or with a +- value
14359243Sobrien */
14459243Sobrien/*ARGSUSED*/
14559243Sobrienvoid
146167465Smpdonice(Char **v, struct command *c)
14759243Sobrien{
148145479Smp    Char *cp;
14959243Sobrien    int	    nval = 0;
15059243Sobrien
15159243Sobrien    USE(c);
15259243Sobrien    v++, cp = *v++;
15359243Sobrien    if (cp == 0)
15459243Sobrien	nval = 4;
15559243Sobrien    else if (*v	== 0 &&	any("+-", cp[0]))
15659243Sobrien	nval = getn(cp);
157316957Sdchagin#if defined(HAVE_SETPRIORITY) && defined(PRIO_PROCESS)
15883098Smp    if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno)
15983098Smp	stderror(ERR_SYSTEM, "setpriority", strerror(errno));
160316957Sdchagin#else /* !HAVE_SETPRIORITY || !PRIO_PROCESS */
16159243Sobrien    (void) nice(nval);
162316957Sdchagin#endif /* HAVE_SETPRIORITY && PRIO_PROCESS */
16359243Sobrien}
16459243Sobrien
16559243Sobrien#ifdef BSDTIMES
16659243Sobrienvoid
167167465Smpruadd(struct sysrusage *ru, struct sysrusage *ru2)
16859243Sobrien{
16959243Sobrien    tvadd(&ru->ru_utime, &ru2->ru_utime);
17059243Sobrien    tvadd(&ru->ru_stime, &ru2->ru_stime);
171145479Smp#ifndef _OSD_POSIX
17259243Sobrien    if (ru2->ru_maxrss > ru->ru_maxrss)
17359243Sobrien	ru->ru_maxrss =	ru2->ru_maxrss;
17459243Sobrien
17559243Sobrien    ru->ru_ixrss += ru2->ru_ixrss;
17659243Sobrien    ru->ru_idrss += ru2->ru_idrss;
17759243Sobrien    ru->ru_isrss += ru2->ru_isrss;
17859243Sobrien    ru->ru_minflt += ru2->ru_minflt;
17959243Sobrien    ru->ru_majflt += ru2->ru_majflt;
18059243Sobrien    ru->ru_nswap += ru2->ru_nswap;
18159243Sobrien    ru->ru_inblock += ru2->ru_inblock;
18259243Sobrien    ru->ru_oublock += ru2->ru_oublock;
18359243Sobrien    ru->ru_msgsnd += ru2->ru_msgsnd;
18459243Sobrien    ru->ru_msgrcv += ru2->ru_msgrcv;
18559243Sobrien    ru->ru_nsignals += ru2->ru_nsignals;
18659243Sobrien    ru->ru_nvcsw += ru2->ru_nvcsw;
18759243Sobrien    ru->ru_nivcsw += ru2->ru_nivcsw;
188145479Smp#endif /*bs2000*/
18959243Sobrien
19059243Sobrien# ifdef	convex
19159243Sobrien    tvadd(&ru->ru_exutime, &ru2->ru_exutime);
19259243Sobrien    ru->ru_utotal += ru2->ru_utotal;
19359243Sobrien    ru->ru_usamples += ru2->ru_usamples;
19459243Sobrien    ru->ru_stotal += ru2->ru_stotal;
19559243Sobrien    ru->ru_ssamples += ru2->ru_ssamples;
19659243Sobrien# endif	/* convex */
19759243Sobrien}
19859243Sobrien
19959243Sobrien#else /* BSDTIMES */
20059243Sobrien# ifdef	_SEQUENT_
20159243Sobrienvoid
202167465Smpruadd(struct process_stats *ru, struct process_stats *ru2)
20359243Sobrien{
20459243Sobrien    tvadd(&ru->ps_utime, &ru2->ps_utime);
20559243Sobrien    tvadd(&ru->ps_stime, &ru2->ps_stime);
20659243Sobrien    if (ru2->ps_maxrss > ru->ps_maxrss)
20759243Sobrien	ru->ps_maxrss =	ru2->ps_maxrss;
20859243Sobrien
20959243Sobrien    ru->ps_pagein += ru2->ps_pagein;
21059243Sobrien    ru->ps_reclaim += ru2->ps_reclaim;
21159243Sobrien    ru->ps_zerofill += ru2->ps_zerofill;
21259243Sobrien    ru->ps_pffincr += ru2->ps_pffincr;
21359243Sobrien    ru->ps_pffdecr += ru2->ps_pffdecr;
21459243Sobrien    ru->ps_swap	+= ru2->ps_swap;
21559243Sobrien    ru->ps_syscall += ru2->ps_syscall;
21659243Sobrien    ru->ps_volcsw += ru2->ps_volcsw;
21759243Sobrien    ru->ps_involcsw += ru2->ps_involcsw;
21859243Sobrien    ru->ps_signal += ru2->ps_signal;
21959243Sobrien    ru->ps_lread += ru2->ps_lread;
22059243Sobrien    ru->ps_lwrite += ru2->ps_lwrite;
22159243Sobrien    ru->ps_bread += ru2->ps_bread;
22259243Sobrien    ru->ps_bwrite += ru2->ps_bwrite;
22359243Sobrien    ru->ps_phread += ru2->ps_phread;
22459243Sobrien    ru->ps_phwrite += ru2->ps_phwrite;
22559243Sobrien}
22659243Sobrien
22759243Sobrien# endif	/* _SEQUENT_ */
22859243Sobrien#endif /* BSDTIMES */
22959243Sobrien
23059243Sobrien#ifdef BSDTIMES
23159243Sobrien
23259243Sobrien/*
23359243Sobrien * PWP:	the LOG1024 and	pagetok	stuff taken from the top command,
23459243Sobrien * written by William LeFebvre
23559243Sobrien */
23659243Sobrien/* Log base 2 of 1024 is 10 (2^10 == 1024) */
23759243Sobrien#define	LOG1024		10
23859243Sobrien
23959243Sobrien/* Convert clicks (kernel pages) to kbytes ... */
24059243Sobrien/* If there is no PGSHIFT defined, assume it is	11 */
24159243Sobrien/* Is this needed for compatability with some old flavor of 4.2	or 4.1?	*/
24259243Sobrien#ifdef SUNOS4
24359243Sobrien# ifndef PGSHIFT
24459243Sobrien#  define pagetok(size)	  ((size) << 1)
24559243Sobrien# else
24659243Sobrien#  if PGSHIFT>10
24759243Sobrien#   define pagetok(size)   ((size) << (PGSHIFT - LOG1024))
24859243Sobrien#  else
24959243Sobrien#   define pagetok(size)   ((size) >> (LOG1024 - PGSHIFT))
25059243Sobrien#  endif
25159243Sobrien# endif
25259243Sobrien#endif
25359243Sobrien
25459243Sobrien/*
25559243Sobrien * if any other	machines return	wierd values in	the ru_i* stuff, put
25659243Sobrien * the adjusting macro here:
25759243Sobrien */
25859243Sobrien#ifdef SUNOS4
25959243Sobrien# define IADJUST(i)	(pagetok(i)/2)
26059243Sobrien#else /* SUNOS4	*/
26159243Sobrien# ifdef	convex
26259243Sobrien   /*
26359243Sobrien    * convex has megabytes * CLK_TCK
26459243Sobrien    * multiply by 100 since we use time	in 100ths of a second in prusage
26559243Sobrien    */
26659243Sobrien#  define IADJUST(i) (((i) << 10) / CLK_TCK * 100)
26759243Sobrien# else /* convex */
26859243Sobrien#  define IADJUST(i)	(i)
26959243Sobrien# endif	/* convex */
27059243Sobrien#endif /* SUNOS4 */
27159243Sobrien
27259243Sobrienvoid
273167465Smpprusage(struct sysrusage *r0, struct sysrusage *r1, timeval_t *e, timeval_t *b)
27459243Sobrien
27559243Sobrien#else /* BSDTIMES */
27659243Sobrien# ifdef	_SEQUENT_
27759243Sobrienvoid
278167465Smpprusage(struct process_stats *r0, struct process_stats *r1, timeval_t e,
279167465Smp	timeval_t b)
28059243Sobrien
28159243Sobrien# else /* _SEQUENT_ */
282167465Smp#  ifndef POSIX
28359243Sobrienvoid
284167465Smpprusage(struct tms *bs, struct tms *es, time_t e, time_t b)
28559243Sobrien#  else	/* POSIX */
286167465Smpvoid
287167465Smpprusage(struct tms *bs, struct tms *es, clock_t e, clock_t b)
28859243Sobrien#  endif /* POSIX */
28959243Sobrien# endif	/* _SEQUENT_ */
29059243Sobrien#endif /* BSDTIMES */
29159243Sobrien{
292316957Sdchagin    int ohaderr = haderr;
29359243Sobrien#ifdef BSDTIMES
294145479Smp    time_t t =
29559243Sobrien    (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec)	* 100 +
29659243Sobrien    (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
29759243Sobrien    (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec)	* 100 +
29859243Sobrien    (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
29959243Sobrien
30059243Sobrien#else
30159243Sobrien# ifdef	_SEQUENT_
302145479Smp    time_t t =
30359243Sobrien    (r1->ps_utime.tv_sec - r0->ps_utime.tv_sec)	* 100 +
30459243Sobrien    (r1->ps_utime.tv_usec - r0->ps_utime.tv_usec) / 10000 +
30559243Sobrien    (r1->ps_stime.tv_sec - r0->ps_stime.tv_sec)	* 100 +
30659243Sobrien    (r1->ps_stime.tv_usec - r0->ps_stime.tv_usec) / 10000;
30759243Sobrien
30859243Sobrien# else /* _SEQUENT_ */
30959243Sobrien#  ifndef POSIX
310145479Smp    time_t t =	(es->tms_utime - bs->tms_utime +
31159243Sobrien			 es->tms_stime - bs->tms_stime)	* 100 /	HZ;
31259243Sobrien
31359243Sobrien#  else	/* POSIX */
314145479Smp    clock_t t = (es->tms_utime	- bs->tms_utime	+
31559243Sobrien			  es->tms_stime	- bs->tms_stime) * 100 / clk_tck;
31659243Sobrien
31759243Sobrien#  endif /* POSIX */
31859243Sobrien# endif	/* _SEQUENT_ */
31959243Sobrien#endif /* BSDTIMES */
32059243Sobrien
321145479Smp    const char *cp;
322145479Smp    long i;
323145479Smp    struct varent *vp = adrof(STRtime);
32459243Sobrien
32559243Sobrien#ifdef BSDTIMES
32659243Sobrien# ifdef	convex
32759243Sobrien    static struct system_information sysinfo;
32859243Sobrien    long long memtmp;	/* let memory calculations exceede 2Gb */
32959243Sobrien# endif	/* convex */
33059243Sobrien    int	    ms = (int)
33159243Sobrien    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
33259243Sobrien
33359243Sobrien    cp = "%Uu %Ss %E %P	%X+%Dk %I+%Oio %Fpf+%Ww";
334316957Sdchagin    haderr = 0;
33559243Sobrien#else /* !BSDTIMES */
33659243Sobrien# ifdef	_SEQUENT_
33759243Sobrien    int	    ms = (int)
33859243Sobrien    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
33959243Sobrien
34059243Sobrien    cp = "%Uu %Ss %E %P	%I+%Oio	%Fpf+%Ww";
341316957Sdchagin    haderr = 0;
34259243Sobrien# else /* !_SEQUENT_ */
34359243Sobrien#  ifndef POSIX
34459243Sobrien    time_t ms = ((time_t)((e - b) / HZ) * 100) +
34559243Sobrien		 (time_t)(((e - b) % HZ) * 100) / HZ;
34659243Sobrien#  else	/* POSIX */
34759243Sobrien    clock_t ms = ((clock_t)((e - b) / clk_tck) * 100) +
34859243Sobrien		  (clock_t)(((e - b) % clk_tck) * 100) / clk_tck;
34959243Sobrien#  endif /* POSIX */
35059243Sobrien
35159243Sobrien    cp = "%Uu %Ss %E %P";
352316957Sdchagin    haderr = 0;
35359243Sobrien
35459243Sobrien    /*
35559243Sobrien     * the tms stuff is	not very precise, so we	fudge it.
35659243Sobrien     * granularity fix:	can't be more than 100%
35759243Sobrien     * this breaks in multi-processor systems...
35859243Sobrien     * maybe I should take it out and let people see more then 100%
35959243Sobrien     * utilizations.
36059243Sobrien     */
36159243Sobrien#  if 0
36259243Sobrien    if (ms < t && ms !=	0)
36359243Sobrien	ms = t;
36459243Sobrien#  endif
36559243Sobrien# endif	/*! _SEQUENT_ */
36659243Sobrien#endif /* !BSDTIMES */
36759243Sobrien#ifdef TDEBUG
36859243Sobrien    xprintf("es->tms_utime %lu bs->tms_utime %lu\n",
369231990Smp	    (unsigned long)es->tms_utime, (unsigned long)bs->tms_utime);
37059243Sobrien    xprintf("es->tms_stime %lu bs->tms_stime %lu\n",
371231990Smp	    (unsigned long)es->tms_stime, (unsigned long)bs->tms_stime);
372231990Smp    xprintf("ms	%llu e %p b %p\n", (unsigned long long)ms, e, b);
373231990Smp    xprintf("t %llu\n", (unsigned long long)t);
37459243Sobrien#endif /* TDEBUG */
37559243Sobrien
376100616Smp    if (vp && vp->vec && vp->vec[0] && vp->vec[1])
37759243Sobrien	cp = short2str(vp->vec[1]);
37859243Sobrien    for	(; *cp;	cp++)
37959243Sobrien	if (*cp	!= '%')
38059243Sobrien	    xputchar(*cp);
38159243Sobrien	else if	(cp[1])
38259243Sobrien	    switch (*++cp) {
38359243Sobrien
38459243Sobrien	    case 'U':		/* user	CPU time used */
38559243Sobrien#ifdef BSDTIMES
38659243Sobrien		pdeltat(&r1->ru_utime, &r0->ru_utime);
38759243Sobrien#else
38859243Sobrien# ifdef	_SEQUENT_
38959243Sobrien		pdeltat(&r1->ps_utime, &r0->ps_utime);
39059243Sobrien# else /* _SEQUENT_ */
39159243Sobrien#  ifndef POSIX
39259243Sobrien		pdtimet(es->tms_utime, bs->tms_utime);
39359243Sobrien#  else	/* POSIX */
39459243Sobrien		pdtimet(es->tms_utime, bs->tms_utime);
39559243Sobrien#  endif /* POSIX */
39659243Sobrien# endif	/* _SEQUENT_ */
39759243Sobrien#endif /* BSDTIMES */
39859243Sobrien		break;
39959243Sobrien
40059243Sobrien	    case 'S':		/* system CPU time used	*/
40159243Sobrien#ifdef BSDTIMES
40259243Sobrien		pdeltat(&r1->ru_stime, &r0->ru_stime);
40359243Sobrien#else
40459243Sobrien# ifdef	_SEQUENT_
40559243Sobrien		pdeltat(&r1->ps_stime, &r0->ps_stime);
40659243Sobrien# else /* _SEQUENT_ */
40759243Sobrien#  ifndef POSIX
40859243Sobrien		pdtimet(es->tms_stime, bs->tms_stime);
40959243Sobrien#  else	/* POSIX */
41059243Sobrien		pdtimet(es->tms_stime, bs->tms_stime);
41159243Sobrien#  endif /* POSIX */
41259243Sobrien# endif	/* _SEQUENT_ */
41359243Sobrien#endif /* BSDTIMES */
41459243Sobrien		break;
41559243Sobrien
41659243Sobrien	    case 'E':		/* elapsed (wall-clock)	time */
41759243Sobrien#ifdef BSDTIMES
41859243Sobrien		pcsecs((long) ms);
41959243Sobrien#else /* BSDTIMES */
42059243Sobrien		pcsecs(ms);
42159243Sobrien#endif /* BSDTIMES */
42259243Sobrien		break;
42359243Sobrien
42459243Sobrien	    case 'P':		/* percent time	spent running */
42559243Sobrien		/* check if the	process	did not	run */
42659243Sobrien#ifdef convex
42759243Sobrien		/*
42859243Sobrien		 * scale the cpu %- ages by the	number of processors
42959243Sobrien		 * available on	this machine
43059243Sobrien		 */
43159243Sobrien		if ((sysinfo.cpu_count == 0) &&
43259243Sobrien		    (getsysinfo(SYSINFO_SIZE, &sysinfo)	< 0))
43359243Sobrien		    sysinfo.cpu_count =	1;
43459415Sobrien		    i =	(ms == 0) ? 0 :	(t * 1000.0 / (ms * sysinfo.cpu_count));
43559243Sobrien#else /* convex	*/
43661521Sobrien		i = (ms	== 0) ?	0 : (long)(t * 1000.0 / ms);
43759243Sobrien#endif /* convex */
43859243Sobrien		xprintf("%ld.%01ld%%", i / 10, i % 10);	/* nn.n% */
43959243Sobrien		break;
44059243Sobrien
44159243Sobrien#ifdef BSDTIMES
44259243Sobrien	    case 'W':		/* number of swaps */
443145479Smp#ifdef _OSD_POSIX
444145479Smp		i = 0;
445145479Smp#else
44659243Sobrien		i = r1->ru_nswap - r0->ru_nswap;
447145479Smp#endif
44859243Sobrien		xprintf("%ld", i);
44959243Sobrien		break;
45059243Sobrien
45159243Sobrien#ifdef convex
45259243Sobrien	    case 'X':		/* (average) shared text size */
45359243Sobrien		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_ixrss -
45459243Sobrien				 (long long)r0->ru_ixrss) /
45559243Sobrien			 (long long)t);
45659243Sobrien		xprintf("%lu", (unsigned long)memtmp);
45759243Sobrien		break;
45859243Sobrien
45959243Sobrien	    case 'D':		/* (average) unshared data size	*/
46059243Sobrien		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_idrss +
46159243Sobrien				 (long long)r1->ru_isrss -
46259243Sobrien				 ((long	long)r0->ru_idrss +
46359243Sobrien				  (long	long)r0->ru_isrss)) /
46459243Sobrien			 (long long)t);
46559243Sobrien		xprintf("%lu", (unsigned long)memtmp);
46659243Sobrien		break;
46759243Sobrien
46859243Sobrien	    case 'K':		/* (average) total data	memory used  */
46959243Sobrien		memtmp = (t == 0 ? 0LL : IADJUST(((long	long)r1->ru_ixrss +
47059243Sobrien				  (long	long)r1->ru_isrss +
47159243Sobrien				  (long	long)r1->ru_idrss) -
47259243Sobrien				  ((long long)r0->ru_ixrss +
47359243Sobrien				   (long long)r0->ru_idrss +
47459243Sobrien				   (long long)r0->ru_isrss)) /
47559243Sobrien			 (long long)t);
47659243Sobrien		xprintf("%lu", (unsigned long)memtmp);
47759243Sobrien		break;
47859243Sobrien#else /* !convex */
47959243Sobrien	    case 'X':		/* (average) shared text size */
480145479Smp#ifdef _OSD_POSIX
481145479Smp		xprintf("0",0);
482145479Smp#else
483231990Smp		xprintf("%lld", (long long)(t == 0 ?	0L :
484231990Smp			IADJUST(r1->ru_ixrss - r0->ru_ixrss) / t));
485145479Smp#endif
48659243Sobrien		break;
48759243Sobrien
48859243Sobrien	    case 'D':		/* (average) unshared data size	*/
489145479Smp#ifdef _OSD_POSIX
490145479Smp		xprintf("0",0);
491145479Smp#else
492231990Smp		xprintf("%lld", (long long)(t == 0 ?	0L :
49359243Sobrien			IADJUST(r1->ru_idrss + r1->ru_isrss -
494231990Smp				(r0->ru_idrss +	r0->ru_isrss)) / t));
495145479Smp#endif
49659243Sobrien		break;
49759243Sobrien
49859243Sobrien	    case 'K':		/* (average) total data	memory used  */
499145479Smp#ifdef _OSD_POSIX
500145479Smp		xprintf("0",0);
501145479Smp#else
502231990Smp		xprintf("%lld", (long long)(t == 0 ? 0L :
50359243Sobrien			IADJUST((r1->ru_ixrss +	r1->ru_isrss + r1->ru_idrss) -
504231990Smp			   (r0->ru_ixrss + r0->ru_idrss	+ r0->ru_isrss)) / t));
505145479Smp#endif
50659243Sobrien		break;
50759243Sobrien#endif /* convex */
50859243Sobrien	    case 'M':		/* max.	Resident Set Size */
50959243Sobrien#ifdef SUNOS4
510231990Smp		xprintf("%ld", (long)pagetok(r1->ru_maxrss));
51159243Sobrien#else
51259243Sobrien# ifdef	convex
513231990Smp		xprintf("%ld", (long)(r1->ru_maxrss * 4L));
51459243Sobrien# else /* !convex */
515145479Smp#  ifdef _OSD_POSIX
516145479Smp		xprintf("0",0);
517145479Smp#  else
518231990Smp		xprintf("%ld", (long)r1->ru_maxrss);
519145479Smp#  endif
52059243Sobrien# endif	/* convex */
52159243Sobrien#endif /* SUNOS4 */
52259243Sobrien		break;
52359243Sobrien
52459243Sobrien	    case 'F':		/* page	faults */
525145479Smp#ifdef _OSD_POSIX
526145479Smp		xprintf("0",0);
527145479Smp#else
528231990Smp		xprintf("%ld", (long)(r1->ru_majflt - r0->ru_majflt));
529145479Smp#endif
53059243Sobrien		break;
53159243Sobrien
53259243Sobrien	    case 'R':		/* page	reclaims */
533145479Smp#ifdef _OSD_POSIX
534145479Smp		xprintf("0",0);
535145479Smp#else
536231990Smp		xprintf("%ld", (long)(r1->ru_minflt - r0->ru_minflt));
537145479Smp#endif
53859243Sobrien		break;
53959243Sobrien
54059243Sobrien	    case 'I':		/* FS blocks in	*/
541145479Smp#ifdef _OSD_POSIX
542145479Smp		xprintf("0",0);
543145479Smp#else
544231990Smp		xprintf("%ld", (long)(r1->ru_inblock - r0->ru_inblock));
545145479Smp#endif
54659243Sobrien		break;
54759243Sobrien
54859243Sobrien	    case 'O':		/* FS blocks out */
549145479Smp#ifdef _OSD_POSIX
550145479Smp		xprintf("0",0);
551145479Smp#else
552231990Smp		xprintf("%ld", (long)(r1->ru_oublock - r0->ru_oublock));
553145479Smp#endif
55459243Sobrien		break;
55559243Sobrien
55659243Sobrien# ifdef	convex
55759243Sobrien	    case 'C':			/*  CPU	parallelization	factor */
55859243Sobrien		if (r1->ru_usamples	!= 0LL)	{
55959243Sobrien		    long long parr = ((r1->ru_utotal * 100LL) /
56059243Sobrien				      r1->ru_usamples);
56159243Sobrien		    xprintf("%d.%02d", (int)(parr/100), (int)(parr%100));
56259243Sobrien		} else
56359243Sobrien		    xprintf("?");
56459243Sobrien		break;
56559243Sobrien# endif	/* convex */
56659243Sobrien	    case 'r':		/* PWP:	socket messages	recieved */
567145479Smp#ifdef _OSD_POSIX
568145479Smp		xprintf("0",0);
569145479Smp#else
570231990Smp		xprintf("%ld", (long)(r1->ru_msgrcv - r0->ru_msgrcv));
571145479Smp#endif
57259243Sobrien		break;
57359243Sobrien
57459243Sobrien	    case 's':		/* PWP:	socket messages	sent */
575145479Smp#ifdef _OSD_POSIX
576145479Smp		xprintf("0",0);
577145479Smp#else
578231990Smp		xprintf("%ld", (long)(r1->ru_msgsnd - r0->ru_msgsnd));
579145479Smp#endif
58059243Sobrien		break;
58159243Sobrien
58259243Sobrien	    case 'k':		/* PWP:	signals	received */
583145479Smp#ifdef _OSD_POSIX
584145479Smp		xprintf("0",0);
585145479Smp#else
586231990Smp		xprintf("%ld", (long)(r1->ru_nsignals - r0->ru_nsignals));
587145479Smp#endif
58859243Sobrien		break;
58959243Sobrien
59059243Sobrien	    case 'w':		/* PWP:	voluntary context switches (waits) */
591145479Smp#ifdef _OSD_POSIX
592145479Smp		xprintf("0",0);
593145479Smp#else
594231990Smp		xprintf("%ld", (long)(r1->ru_nvcsw - r0->ru_nvcsw));
595145479Smp#endif
59659243Sobrien		break;
59759243Sobrien
59859243Sobrien	    case 'c':		/* PWP:	involuntary context switches */
599145479Smp#ifdef _OSD_POSIX
600145479Smp		xprintf("0",0);
601145479Smp#else
602231990Smp		xprintf("%ld", (long)(r1->ru_nivcsw - r0->ru_nivcsw));
603145479Smp#endif
60459243Sobrien		break;
60559243Sobrien#else /* BSDTIMES */
60659243Sobrien# ifdef	_SEQUENT_
60759243Sobrien	    case 'W':		/* number of swaps */
60859243Sobrien		i = r1->ps_swap	- r0->ps_swap;
609231990Smp		xprintf("%ld", (long)i);
61059243Sobrien		break;
61159243Sobrien
61259243Sobrien	    case 'M':
613231990Smp		xprintf("%ld", (long)r1->ps_maxrss);
61459243Sobrien		break;
61559243Sobrien
61659243Sobrien	    case 'F':
617231990Smp		xprintf("%ld", (long)(r1->ps_pagein - r0->ps_pagein));
61859243Sobrien		break;
61959243Sobrien
62059243Sobrien	    case 'R':
621231990Smp		xprintf("%ld", (long)(r1->ps_reclaim -	r0->ps_reclaim));
62259243Sobrien		break;
62359243Sobrien
62459243Sobrien	    case 'I':
625231990Smp		xprintf("%ld", (long)(r1->ps_bread - r0->ps_bread));
62659243Sobrien		break;
62759243Sobrien
62859243Sobrien	    case 'O':
629231990Smp		xprintf("%ld", (long)(r1->ps_bwrite - r0->ps_bwrite));
63059243Sobrien		break;
63159243Sobrien
63259243Sobrien	    case 'k':
633231990Smp		xprintf("%ld", (long)(r1->ps_signal - r0->ps_signal));
63459243Sobrien		break;
63559243Sobrien
63659243Sobrien	    case 'w':
637231990Smp		xprintf("%ld", (long)(r1->ps_volcsw - r0->ps_volcsw));
63859243Sobrien		break;
63959243Sobrien
64059243Sobrien	    case 'c':
64159243Sobrien		xprintf("%ld", r1->ps_involcsw - r0->ps_involcsw);
64259243Sobrien		break;
64359243Sobrien
64459243Sobrien	    case 'Z':
645231990Smp		xprintf("%ld", (long)(r1->ps_zerofill - r0->ps_zerofill));
64659243Sobrien		break;
64759243Sobrien
64859243Sobrien	    case 'i':
649231990Smp		xprintf("%ld", (long)(r1->ps_pffincr - r0->ps_pffincr));
65059243Sobrien		break;
65159243Sobrien
65259243Sobrien	    case 'd':
653231990Smp		xprintf("%ld", (long)(r1->ps_pffdecr - r0->ps_pffdecr));
65459243Sobrien		break;
65559243Sobrien
65659243Sobrien	    case 'Y':
657231990Smp		xprintf("%ld", (long)(r1->ps_syscall - r0->ps_syscall));
65859243Sobrien		break;
65959243Sobrien
66059243Sobrien	    case 'l':
661231990Smp		xprintf("%ld", (long)(r1->ps_lread - r0->ps_lread));
66259243Sobrien		break;
66359243Sobrien
66459243Sobrien	    case 'm':
665231990Smp		xprintf("%ld", (long)(r1->ps_lwrite - r0->ps_lwrite));
66659243Sobrien		break;
66759243Sobrien
66859243Sobrien	    case 'p':
669231990Smp		xprintf("%ld", (long)(r1->ps_phread - r0->ps_phread));
67059243Sobrien		break;
67159243Sobrien
67259243Sobrien	    case 'q':
673231990Smp		xprintf("%ld", (long)(r1->ps_phwrite - r0->ps_phwrite));
67459243Sobrien		break;
67559243Sobrien# endif	/* _SEQUENT_ */
67659243Sobrien#endif /* BSDTIMES */
67759243Sobrien	    default:
67859243Sobrien		break;
67959243Sobrien	    }
68059243Sobrien    xputchar('\n');
681316957Sdchagin    haderr = ohaderr;
68259243Sobrien}
68359243Sobrien
68459243Sobrien#if defined(BSDTIMES) || defined(_SEQUENT_)
68559243Sobrienstatic void
686167465Smppdeltat(timeval_t *t1, timeval_t *t0)
68759243Sobrien{
68859243Sobrien    timeval_t td;
68959243Sobrien
69059243Sobrien    tvsub(&td, t1, t0);
691231990Smp    xprintf("%lld.%03ld", (long long)td.tv_sec, (long)td.tv_usec / 1000L);
69259243Sobrien}
69359243Sobrien
69459243Sobrienstatic void
695167465Smptvadd(timeval_t *tsum, timeval_t *t0)
69659243Sobrien{
69759243Sobrien
69859243Sobrien    tsum->tv_sec += t0->tv_sec;
69959243Sobrien    tsum->tv_usec += t0->tv_usec;
70059243Sobrien    if (tsum->tv_usec >= 1000000)
70159243Sobrien	tsum->tv_sec++,	tsum->tv_usec -= 1000000;
70259243Sobrien}
70359243Sobrien
70459243Sobrienvoid
705167465Smptvsub(timeval_t *tdiff, timeval_t *t1, timeval_t *t0)
70659243Sobrien{
70759243Sobrien
70859243Sobrien    tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
70959243Sobrien    tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
71059243Sobrien    if (tdiff->tv_usec < 0)
71159243Sobrien	tdiff->tv_sec--, tdiff->tv_usec	+= 1000000;
71259243Sobrien}
71359243Sobrien
71459243Sobrien#else /* !BSDTIMES && !_SEQUENT_ */
71559243Sobrienstatic void
71659243Sobrien#ifndef	POSIX
717167465Smppdtimet(time_t eval, time_t bval)
71859243Sobrien
71959243Sobrien#else /* POSIX */
720167465Smppdtimet(clock_t eval, clock_t bval)
72159243Sobrien
72259243Sobrien#endif /* POSIX	*/
72359243Sobrien{
72459243Sobrien#ifndef	POSIX
72559243Sobrien    time_t  val;
72659243Sobrien
72759243Sobrien#else /* POSIX */
72859243Sobrien    clock_t val;
72959243Sobrien
73059243Sobrien#endif /* POSIX	*/
73159243Sobrien
73259243Sobrien#ifndef	POSIX
73359243Sobrien    val	= (eval	- bval)	* 100 /	HZ;
73459243Sobrien#else /* POSIX */
73559243Sobrien    val	= (eval	- bval)	* 100 /	clk_tck;
73659243Sobrien#endif /* POSIX	*/
73759243Sobrien
738231990Smp    xprintf("%lld.%02ld", (long long)(val / 100),
739231990Smp	(long long)(val - (val / 100 * 100)));
74059243Sobrien}
74159243Sobrien#endif /* BSDTIMES || _SEQUENT_	*/
742