sh.time.c revision 100616
1100616Smp/* $Header: /src/pub/tcsh/sh.time.c,v 3.25 2002/06/25 19:02:11 christos Exp $ */
259243Sobrien/*
359243Sobrien * sh.time.c: Shell time keeping and printing.
459243Sobrien */
559243Sobrien/*-
659243Sobrien * Copyright (c) 1980, 1991 The	Regents	of the University of California.
759243Sobrien * All rights reserved.
859243Sobrien *
959243Sobrien * Redistribution and use in source and	binary forms, with or without
1059243Sobrien * modification, are permitted provided	that the following conditions
1159243Sobrien * are met:
1259243Sobrien * 1. Redistributions of source	code must retain the above copyright
1359243Sobrien *    notice, this list	of conditions and the following	disclaimer.
1459243Sobrien * 2. Redistributions in binary	form must reproduce the	above copyright
1559243Sobrien *    notice, this list	of conditions and the following	disclaimer in the
1659243Sobrien *    documentation and/or other materials provided with the distribution.
17100616Smp * 3. Neither the name of the University nor the names of its contributors
1859243Sobrien *    may be used to endorse or	promote	products derived from this software
1959243Sobrien *    without specific prior written permission.
2059243Sobrien *
2159243Sobrien * THIS	SOFTWARE IS PROVIDED BY	THE REGENTS AND	CONTRIBUTORS ``AS IS'' AND
2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2459243Sobrien * ARE DISCLAIMED.  IN NO EVENT	SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR	CONSEQUENTIAL
2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2759243Sobrien * OR SERVICES;	LOSS OF	USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3159243Sobrien * SUCH	DAMAGE.
3259243Sobrien */
3359243Sobrien#include "sh.h"
3459243Sobrien
35100616SmpRCSID("$Id: sh.time.c,v 3.25 2002/06/25 19:02:11 christos Exp $")
3659243Sobrien
3759243Sobrien#ifdef SUNOS4
3859243Sobrien# include <machine/param.h>
3959243Sobrien#endif /* SUNOS4 */
4059243Sobrien
4159243Sobrien/*
4259243Sobrien * C Shell - routines handling process timing and niceing
4359243Sobrien */
4459243Sobrien#ifdef BSDTIMES
4559243Sobrien# ifndef RUSAGE_SELF
4659243Sobrien#  define	RUSAGE_SELF	0
4759243Sobrien#  define	RUSAGE_CHILDREN	-1
4859243Sobrien# endif	/* RUSAGE_SELF */
4959243Sobrien#else /* BSDTIMES */
5059243Sobrienstruct tms times0;
5159243Sobrien#endif /* BSDTIMES */
5259243Sobrien
5359243Sobrien#if !defined(BSDTIMES) && !defined(_SEQUENT_)
5459243Sobrien# ifdef	POSIX
5559243Sobrienstatic	void	pdtimet	__P((clock_t, clock_t));
5659243Sobrien# else /* ! POSIX */
5759243Sobrienstatic	void	pdtimet	__P((time_t, time_t));
5859243Sobrien# endif	/* ! POSIX */
5959243Sobrien#else /* BSDTIMES || _SEQUENT_ */
6059243Sobrienstatic	void	tvadd	__P((timeval_t *, timeval_t *));
6159243Sobrienstatic	void	pdeltat	__P((timeval_t *, timeval_t *));
6259243Sobrien#endif /* BSDTIMES || _SEQUENT_	*/
6359243Sobrien
6459243Sobrienvoid
6559243Sobriensettimes()
6659243Sobrien{
6759243Sobrien#ifdef BSDTIMES
6859243Sobrien    struct sysrusage ruch;
6959243Sobrien#ifdef convex
7059243Sobrien    memset(&ru0, 0, sizeof(ru0));
7159243Sobrien    memset(&ruch, 0, sizeof(ruch));
7259243Sobrien#endif /* convex */
7359243Sobrien
7459243Sobrien    (void) gettimeofday(&time0,	NULL);
7559243Sobrien    (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru0);
7659243Sobrien    (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
7759243Sobrien    ruadd(&ru0,	&ruch);
7859243Sobrien#else
7959243Sobrien# ifdef	_SEQUENT_
8059243Sobrien    struct process_stats ruch;
8159243Sobrien
8259243Sobrien    (void) get_process_stats(&time0, PS_SELF, &ru0, &ruch);
8359243Sobrien    ruadd(&ru0,	&ruch);
8459243Sobrien# else	/* _SEQUENT_ */
8559415Sobrien    seconds0 = time(NULL);
8659243Sobrien#  ifndef COHERENT
8759243Sobrien    time0 = times(&times0);
8859243Sobrien#  else	/* !COHERENT */
8959415Sobrien    time0 = HZ * seconds0;
9059243Sobrien    times(&times0);
9159243Sobrien#  endif /* !COHERENT */
9259243Sobrien    times0.tms_stime +=	times0.tms_cstime;
9359243Sobrien    times0.tms_utime +=	times0.tms_cutime;
9459243Sobrien    times0.tms_cstime =	0;
9559243Sobrien    times0.tms_cutime =	0;
9659243Sobrien# endif	/* _SEQUENT_ */
9759243Sobrien#endif /* BSDTIMES */
9859243Sobrien}
9959243Sobrien
10059243Sobrien/*
10159243Sobrien * dotime is only called if it is truly	a builtin function and not a
10259243Sobrien * prefix to another command
10359243Sobrien */
10459243Sobrien/*ARGSUSED*/
10559243Sobrienvoid
10659243Sobriendotime(v, c)
10759243Sobrien    Char **v;
10859243Sobrien    struct command *c;
10959243Sobrien{
11059243Sobrien#ifdef BSDTIMES
11159243Sobrien    timeval_t timedol;
11259243Sobrien    struct sysrusage ru1, ruch;
11359243Sobrien#ifdef convex
11459243Sobrien    memset(&ru1, 0, sizeof(ru1));
11559243Sobrien    memset(&ruch, 0, sizeof(ruch));
11659243Sobrien#endif /* convex */
11759243Sobrien
11859243Sobrien    (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru1);
11959243Sobrien    (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
12059243Sobrien    ruadd(&ru1,	&ruch);
12159243Sobrien    (void) gettimeofday(&timedol, NULL);
12259243Sobrien    prusage(&ru0, &ru1,	&timedol, &time0);
12359243Sobrien#else
12459243Sobrien# ifdef	_SEQUENT_
12559243Sobrien    timeval_t timedol;
12659243Sobrien    struct process_stats ru1, ruch;
12759243Sobrien
12859243Sobrien    (void) get_process_stats(&timedol, PS_SELF,	&ru1, &ruch);
12959243Sobrien    ruadd(&ru1,	&ruch);
13059243Sobrien    prusage(&ru0, &ru1,	&timedol, &time0);
13159243Sobrien# else /* _SEQUENT_ */
13259243Sobrien#  ifndef POSIX
13359243Sobrien    time_t  timedol;
13459243Sobrien#  else	/* POSIX */
13559243Sobrien    clock_t timedol;
13659243Sobrien#  endif /* POSIX */
13759243Sobrien
13859243Sobrien    struct tms times_dol;
13959243Sobrien
14059243Sobrien#ifndef	COHERENT
14159243Sobrien    timedol = times(&times_dol);
14259243Sobrien#else
14359243Sobrien    timedol = HZ * time(NULL);
14459243Sobrien    times(&times_dol);
14559243Sobrien#endif
14659243Sobrien    times_dol.tms_stime	+= times_dol.tms_cstime;
14759243Sobrien    times_dol.tms_utime	+= times_dol.tms_cutime;
14859243Sobrien    times_dol.tms_cstime = 0;
14959243Sobrien    times_dol.tms_cutime = 0;
15059243Sobrien    prusage(&times0, &times_dol, timedol, time0);
15159243Sobrien# endif	/* _SEQUENT_ */
15259243Sobrien#endif /* BSDTIMES */
15359243Sobrien    USE(c);
15459243Sobrien    USE(v);
15559243Sobrien}
15659243Sobrien
15759243Sobrien/*
15859243Sobrien * donice is only called when it on the	line by	itself or with a +- value
15959243Sobrien */
16059243Sobrien/*ARGSUSED*/
16159243Sobrienvoid
16259243Sobriendonice(v, c)
16359243Sobrien    register Char **v;
16459243Sobrien    struct command *c;
16559243Sobrien{
16659243Sobrien    register Char *cp;
16759243Sobrien    int	    nval = 0;
16859243Sobrien
16959243Sobrien    USE(c);
17059243Sobrien    v++, cp = *v++;
17159243Sobrien    if (cp == 0)
17259243Sobrien	nval = 4;
17359243Sobrien    else if (*v	== 0 &&	any("+-", cp[0]))
17459243Sobrien	nval = getn(cp);
17559243Sobrien#ifdef BSDNICE
17683098Smp    if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno)
17783098Smp	stderror(ERR_SYSTEM, "setpriority", strerror(errno));
17859243Sobrien#else /* BSDNICE */
17959243Sobrien    (void) nice(nval);
18059243Sobrien#endif /* BSDNICE */
18159243Sobrien}
18259243Sobrien
18359243Sobrien#ifdef BSDTIMES
18459243Sobrienvoid
18559243Sobrienruadd(ru, ru2)
18659243Sobrien    register struct sysrusage *ru,	*ru2;
18759243Sobrien{
18859243Sobrien    tvadd(&ru->ru_utime, &ru2->ru_utime);
18959243Sobrien    tvadd(&ru->ru_stime, &ru2->ru_stime);
19059243Sobrien    if (ru2->ru_maxrss > ru->ru_maxrss)
19159243Sobrien	ru->ru_maxrss =	ru2->ru_maxrss;
19259243Sobrien
19359243Sobrien    ru->ru_ixrss += ru2->ru_ixrss;
19459243Sobrien    ru->ru_idrss += ru2->ru_idrss;
19559243Sobrien    ru->ru_isrss += ru2->ru_isrss;
19659243Sobrien    ru->ru_minflt += ru2->ru_minflt;
19759243Sobrien    ru->ru_majflt += ru2->ru_majflt;
19859243Sobrien    ru->ru_nswap += ru2->ru_nswap;
19959243Sobrien    ru->ru_inblock += ru2->ru_inblock;
20059243Sobrien    ru->ru_oublock += ru2->ru_oublock;
20159243Sobrien    ru->ru_msgsnd += ru2->ru_msgsnd;
20259243Sobrien    ru->ru_msgrcv += ru2->ru_msgrcv;
20359243Sobrien    ru->ru_nsignals += ru2->ru_nsignals;
20459243Sobrien    ru->ru_nvcsw += ru2->ru_nvcsw;
20559243Sobrien    ru->ru_nivcsw += ru2->ru_nivcsw;
20659243Sobrien
20759243Sobrien# ifdef	convex
20859243Sobrien    tvadd(&ru->ru_exutime, &ru2->ru_exutime);
20959243Sobrien    ru->ru_utotal += ru2->ru_utotal;
21059243Sobrien    ru->ru_usamples += ru2->ru_usamples;
21159243Sobrien    ru->ru_stotal += ru2->ru_stotal;
21259243Sobrien    ru->ru_ssamples += ru2->ru_ssamples;
21359243Sobrien# endif	/* convex */
21459243Sobrien}
21559243Sobrien
21659243Sobrien#else /* BSDTIMES */
21759243Sobrien# ifdef	_SEQUENT_
21859243Sobrienvoid
21959243Sobrienruadd(ru, ru2)
22059243Sobrien    register struct process_stats *ru, *ru2;
22159243Sobrien{
22259243Sobrien    tvadd(&ru->ps_utime, &ru2->ps_utime);
22359243Sobrien    tvadd(&ru->ps_stime, &ru2->ps_stime);
22459243Sobrien    if (ru2->ps_maxrss > ru->ps_maxrss)
22559243Sobrien	ru->ps_maxrss =	ru2->ps_maxrss;
22659243Sobrien
22759243Sobrien    ru->ps_pagein += ru2->ps_pagein;
22859243Sobrien    ru->ps_reclaim += ru2->ps_reclaim;
22959243Sobrien    ru->ps_zerofill += ru2->ps_zerofill;
23059243Sobrien    ru->ps_pffincr += ru2->ps_pffincr;
23159243Sobrien    ru->ps_pffdecr += ru2->ps_pffdecr;
23259243Sobrien    ru->ps_swap	+= ru2->ps_swap;
23359243Sobrien    ru->ps_syscall += ru2->ps_syscall;
23459243Sobrien    ru->ps_volcsw += ru2->ps_volcsw;
23559243Sobrien    ru->ps_involcsw += ru2->ps_involcsw;
23659243Sobrien    ru->ps_signal += ru2->ps_signal;
23759243Sobrien    ru->ps_lread += ru2->ps_lread;
23859243Sobrien    ru->ps_lwrite += ru2->ps_lwrite;
23959243Sobrien    ru->ps_bread += ru2->ps_bread;
24059243Sobrien    ru->ps_bwrite += ru2->ps_bwrite;
24159243Sobrien    ru->ps_phread += ru2->ps_phread;
24259243Sobrien    ru->ps_phwrite += ru2->ps_phwrite;
24359243Sobrien}
24459243Sobrien
24559243Sobrien# endif	/* _SEQUENT_ */
24659243Sobrien#endif /* BSDTIMES */
24759243Sobrien
24859243Sobrien#ifdef BSDTIMES
24959243Sobrien
25059243Sobrien/*
25159243Sobrien * PWP:	the LOG1024 and	pagetok	stuff taken from the top command,
25259243Sobrien * written by William LeFebvre
25359243Sobrien */
25459243Sobrien/* Log base 2 of 1024 is 10 (2^10 == 1024) */
25559243Sobrien#define	LOG1024		10
25659243Sobrien
25759243Sobrien/* Convert clicks (kernel pages) to kbytes ... */
25859243Sobrien/* If there is no PGSHIFT defined, assume it is	11 */
25959243Sobrien/* Is this needed for compatability with some old flavor of 4.2	or 4.1?	*/
26059243Sobrien#ifdef SUNOS4
26159243Sobrien# ifndef PGSHIFT
26259243Sobrien#  define pagetok(size)	  ((size) << 1)
26359243Sobrien# else
26459243Sobrien#  if PGSHIFT>10
26559243Sobrien#   define pagetok(size)   ((size) << (PGSHIFT - LOG1024))
26659243Sobrien#  else
26759243Sobrien#   define pagetok(size)   ((size) >> (LOG1024 - PGSHIFT))
26859243Sobrien#  endif
26959243Sobrien# endif
27059243Sobrien#endif
27159243Sobrien
27259243Sobrien/*
27359243Sobrien * if any other	machines return	wierd values in	the ru_i* stuff, put
27459243Sobrien * the adjusting macro here:
27559243Sobrien */
27659243Sobrien#ifdef SUNOS4
27759243Sobrien# define IADJUST(i)	(pagetok(i)/2)
27859243Sobrien#else /* SUNOS4	*/
27959243Sobrien# ifdef	convex
28059243Sobrien   /*
28159243Sobrien    * convex has megabytes * CLK_TCK
28259243Sobrien    * multiply by 100 since we use time	in 100ths of a second in prusage
28359243Sobrien    */
28459243Sobrien#  define IADJUST(i) (((i) << 10) / CLK_TCK * 100)
28559243Sobrien# else /* convex */
28659243Sobrien#  define IADJUST(i)	(i)
28759243Sobrien# endif	/* convex */
28859243Sobrien#endif /* SUNOS4 */
28959243Sobrien
29059243Sobrienvoid
29159243Sobrienprusage(r0, r1,	e, b)
29259243Sobrien    register struct sysrusage *r0,	*r1;
29359243Sobrien    timeval_t *e, *b;
29459243Sobrien
29559243Sobrien#else /* BSDTIMES */
29659243Sobrien# ifdef	_SEQUENT_
29759243Sobrienvoid
29859243Sobrienprusage(r0, r1,	e, b)
29959243Sobrien    register struct process_stats *r0, *r1;
30059243Sobrien    timeval_t *e, *b;
30159243Sobrien
30259243Sobrien# else /* _SEQUENT_ */
30359243Sobrienvoid
30459243Sobrienprusage(bs, es,	e, b)
30559243Sobrien    struct tms *bs, *es;
30659243Sobrien
30759243Sobrien#  ifndef POSIX
30859243Sobrien    time_t  e, b;
30959243Sobrien
31059243Sobrien#  else	/* POSIX */
31159243Sobrien    clock_t e, b;
31259243Sobrien
31359243Sobrien#  endif /* POSIX */
31459243Sobrien# endif	/* _SEQUENT_ */
31559243Sobrien#endif /* BSDTIMES */
31659243Sobrien{
31759243Sobrien#ifdef BSDTIMES
31859243Sobrien    register time_t t =
31959243Sobrien    (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec)	* 100 +
32059243Sobrien    (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
32159243Sobrien    (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec)	* 100 +
32259243Sobrien    (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
32359243Sobrien
32459243Sobrien#else
32559243Sobrien# ifdef	_SEQUENT_
32659243Sobrien    register time_t t =
32759243Sobrien    (r1->ps_utime.tv_sec - r0->ps_utime.tv_sec)	* 100 +
32859243Sobrien    (r1->ps_utime.tv_usec - r0->ps_utime.tv_usec) / 10000 +
32959243Sobrien    (r1->ps_stime.tv_sec - r0->ps_stime.tv_sec)	* 100 +
33059243Sobrien    (r1->ps_stime.tv_usec - r0->ps_stime.tv_usec) / 10000;
33159243Sobrien
33259243Sobrien# else /* _SEQUENT_ */
33359243Sobrien#  ifndef POSIX
33459243Sobrien    register time_t t =	(es->tms_utime - bs->tms_utime +
33559243Sobrien			 es->tms_stime - bs->tms_stime)	* 100 /	HZ;
33659243Sobrien
33759243Sobrien#  else	/* POSIX */
33859243Sobrien    register clock_t t = (es->tms_utime	- bs->tms_utime	+
33959243Sobrien			  es->tms_stime	- bs->tms_stime) * 100 / clk_tck;
34059243Sobrien
34159243Sobrien#  endif /* POSIX */
34259243Sobrien# endif	/* _SEQUENT_ */
34359243Sobrien#endif /* BSDTIMES */
34459243Sobrien
34559243Sobrien    register char *cp;
34659243Sobrien    register long i;
34759243Sobrien    register struct varent *vp = adrof(STRtime);
34859243Sobrien
34959243Sobrien#ifdef BSDTIMES
35059243Sobrien# ifdef	convex
35159243Sobrien    static struct system_information sysinfo;
35259243Sobrien    long long memtmp;	/* let memory calculations exceede 2Gb */
35359243Sobrien# endif	/* convex */
35459243Sobrien    int	    ms = (int)
35559243Sobrien    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
35659243Sobrien
35759243Sobrien    cp = "%Uu %Ss %E %P	%X+%Dk %I+%Oio %Fpf+%Ww";
35859243Sobrien#else /* !BSDTIMES */
35959243Sobrien# ifdef	_SEQUENT_
36059243Sobrien    int	    ms = (int)
36159243Sobrien    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
36259243Sobrien
36359243Sobrien    cp = "%Uu %Ss %E %P	%I+%Oio	%Fpf+%Ww";
36459243Sobrien# else /* !_SEQUENT_ */
36559243Sobrien#  ifndef POSIX
36659243Sobrien    time_t ms = ((time_t)((e - b) / HZ) * 100) +
36759243Sobrien		 (time_t)(((e - b) % HZ) * 100) / HZ;
36859243Sobrien#  else	/* POSIX */
36959243Sobrien    clock_t ms = ((clock_t)((e - b) / clk_tck) * 100) +
37059243Sobrien		  (clock_t)(((e - b) % clk_tck) * 100) / clk_tck;
37159243Sobrien#  endif /* POSIX */
37259243Sobrien
37359243Sobrien    cp = "%Uu %Ss %E %P";
37459243Sobrien
37559243Sobrien    /*
37659243Sobrien     * the tms stuff is	not very precise, so we	fudge it.
37759243Sobrien     * granularity fix:	can't be more than 100%
37859243Sobrien     * this breaks in multi-processor systems...
37959243Sobrien     * maybe I should take it out and let people see more then 100%
38059243Sobrien     * utilizations.
38159243Sobrien     */
38259243Sobrien#  if 0
38359243Sobrien    if (ms < t && ms !=	0)
38459243Sobrien	ms = t;
38559243Sobrien#  endif
38659243Sobrien# endif	/*! _SEQUENT_ */
38759243Sobrien#endif /* !BSDTIMES */
38859243Sobrien#ifdef TDEBUG
38959243Sobrien    xprintf("es->tms_utime %lu bs->tms_utime %lu\n",
39059243Sobrien	    es->tms_utime, bs->tms_utime);
39159243Sobrien    xprintf("es->tms_stime %lu bs->tms_stime %lu\n",
39259243Sobrien	    es->tms_stime, bs->tms_stime);
39359243Sobrien    xprintf("ms	%lu e %lu b %lu\n", ms,	e, b);
39459243Sobrien    xprintf("t %lu\n", t);
39559243Sobrien#endif /* TDEBUG */
39659243Sobrien
397100616Smp    if (vp && vp->vec && vp->vec[0] && vp->vec[1])
39859243Sobrien	cp = short2str(vp->vec[1]);
39959243Sobrien    for	(; *cp;	cp++)
40059243Sobrien	if (*cp	!= '%')
40159243Sobrien	    xputchar(*cp);
40259243Sobrien	else if	(cp[1])
40359243Sobrien	    switch (*++cp) {
40459243Sobrien
40559243Sobrien	    case 'U':		/* user	CPU time used */
40659243Sobrien#ifdef BSDTIMES
40759243Sobrien		pdeltat(&r1->ru_utime, &r0->ru_utime);
40859243Sobrien#else
40959243Sobrien# ifdef	_SEQUENT_
41059243Sobrien		pdeltat(&r1->ps_utime, &r0->ps_utime);
41159243Sobrien# else /* _SEQUENT_ */
41259243Sobrien#  ifndef POSIX
41359243Sobrien		pdtimet(es->tms_utime, bs->tms_utime);
41459243Sobrien#  else	/* POSIX */
41559243Sobrien		pdtimet(es->tms_utime, bs->tms_utime);
41659243Sobrien#  endif /* POSIX */
41759243Sobrien# endif	/* _SEQUENT_ */
41859243Sobrien#endif /* BSDTIMES */
41959243Sobrien		break;
42059243Sobrien
42159243Sobrien	    case 'S':		/* system CPU time used	*/
42259243Sobrien#ifdef BSDTIMES
42359243Sobrien		pdeltat(&r1->ru_stime, &r0->ru_stime);
42459243Sobrien#else
42559243Sobrien# ifdef	_SEQUENT_
42659243Sobrien		pdeltat(&r1->ps_stime, &r0->ps_stime);
42759243Sobrien# else /* _SEQUENT_ */
42859243Sobrien#  ifndef POSIX
42959243Sobrien		pdtimet(es->tms_stime, bs->tms_stime);
43059243Sobrien#  else	/* POSIX */
43159243Sobrien		pdtimet(es->tms_stime, bs->tms_stime);
43259243Sobrien#  endif /* POSIX */
43359243Sobrien# endif	/* _SEQUENT_ */
43459243Sobrien#endif /* BSDTIMES */
43559243Sobrien		break;
43659243Sobrien
43759243Sobrien	    case 'E':		/* elapsed (wall-clock)	time */
43859243Sobrien#ifdef BSDTIMES
43959243Sobrien		pcsecs((long) ms);
44059243Sobrien#else /* BSDTIMES */
44159243Sobrien		pcsecs(ms);
44259243Sobrien#endif /* BSDTIMES */
44359243Sobrien		break;
44459243Sobrien
44559243Sobrien	    case 'P':		/* percent time	spent running */
44659243Sobrien		/* check if the	process	did not	run */
44759243Sobrien#ifdef convex
44859243Sobrien		/*
44959243Sobrien		 * scale the cpu %- ages by the	number of processors
45059243Sobrien		 * available on	this machine
45159243Sobrien		 */
45259243Sobrien		if ((sysinfo.cpu_count == 0) &&
45359243Sobrien		    (getsysinfo(SYSINFO_SIZE, &sysinfo)	< 0))
45459243Sobrien		    sysinfo.cpu_count =	1;
45559415Sobrien		    i =	(ms == 0) ? 0 :	(t * 1000.0 / (ms * sysinfo.cpu_count));
45659243Sobrien#else /* convex	*/
45761521Sobrien		i = (ms	== 0) ?	0 : (long)(t * 1000.0 / ms);
45859243Sobrien#endif /* convex */
45959243Sobrien		xprintf("%ld.%01ld%%", i / 10, i % 10);	/* nn.n% */
46059243Sobrien		break;
46159243Sobrien
46259243Sobrien#ifdef BSDTIMES
46359243Sobrien	    case 'W':		/* number of swaps */
46459243Sobrien		i = r1->ru_nswap - r0->ru_nswap;
46559243Sobrien		xprintf("%ld", i);
46659243Sobrien		break;
46759243Sobrien
46859243Sobrien#ifdef convex
46959243Sobrien	    case 'X':		/* (average) shared text size */
47059243Sobrien		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_ixrss -
47159243Sobrien				 (long long)r0->ru_ixrss) /
47259243Sobrien			 (long long)t);
47359243Sobrien		xprintf("%lu", (unsigned long)memtmp);
47459243Sobrien
47559243Sobrien		break;
47659243Sobrien
47759243Sobrien	    case 'D':		/* (average) unshared data size	*/
47859243Sobrien		memtmp = (t == 0 ? 0LL : IADJUST((long long)r1->ru_idrss +
47959243Sobrien				 (long long)r1->ru_isrss -
48059243Sobrien				 ((long	long)r0->ru_idrss +
48159243Sobrien				  (long	long)r0->ru_isrss)) /
48259243Sobrien			 (long long)t);
48359243Sobrien		xprintf("%lu", (unsigned long)memtmp);
48459243Sobrien		break;
48559243Sobrien
48659243Sobrien	    case 'K':		/* (average) total data	memory used  */
48759243Sobrien		memtmp = (t == 0 ? 0LL : IADJUST(((long	long)r1->ru_ixrss +
48859243Sobrien				  (long	long)r1->ru_isrss +
48959243Sobrien				  (long	long)r1->ru_idrss) -
49059243Sobrien				  ((long long)r0->ru_ixrss +
49159243Sobrien				   (long long)r0->ru_idrss +
49259243Sobrien				   (long long)r0->ru_isrss)) /
49359243Sobrien			 (long long)t);
49459243Sobrien		xprintf("%lu", (unsigned long)memtmp);
49559243Sobrien		break;
49659243Sobrien#else /* !convex */
49759243Sobrien	    case 'X':		/* (average) shared text size */
49859243Sobrien		xprintf("%ld", t == 0 ?	0L :
49959243Sobrien			IADJUST(r1->ru_ixrss - r0->ru_ixrss) / t);
50059243Sobrien		break;
50159243Sobrien
50259243Sobrien	    case 'D':		/* (average) unshared data size	*/
50359243Sobrien		xprintf("%ld", t == 0 ?	0L :
50459243Sobrien			IADJUST(r1->ru_idrss + r1->ru_isrss -
50559243Sobrien				(r0->ru_idrss +	r0->ru_isrss)) / t);
50659243Sobrien		break;
50759243Sobrien
50859243Sobrien	    case 'K':		/* (average) total data	memory used  */
50959243Sobrien		xprintf("%ld", t == 0 ?	0L :
51059243Sobrien			IADJUST((r1->ru_ixrss +	r1->ru_isrss + r1->ru_idrss) -
51159243Sobrien			   (r0->ru_ixrss + r0->ru_idrss	+ r0->ru_isrss)) / t);
51259243Sobrien		break;
51359243Sobrien#endif /* convex */
51459243Sobrien	    case 'M':		/* max.	Resident Set Size */
51559243Sobrien#ifdef SUNOS4
51659243Sobrien		xprintf("%ld", pagetok(r1->ru_maxrss));
51759243Sobrien#else
51859243Sobrien# ifdef	convex
51959243Sobrien		xprintf("%ld", r1->ru_maxrss * 4L);
52059243Sobrien# else /* !convex */
52159243Sobrien		xprintf("%ld", r1->ru_maxrss / 2L);
52259243Sobrien# endif	/* convex */
52359243Sobrien#endif /* SUNOS4 */
52459243Sobrien		break;
52559243Sobrien
52659243Sobrien	    case 'F':		/* page	faults */
52759243Sobrien		xprintf("%ld", r1->ru_majflt - r0->ru_majflt);
52859243Sobrien		break;
52959243Sobrien
53059243Sobrien	    case 'R':		/* page	reclaims */
53159243Sobrien		xprintf("%ld", r1->ru_minflt - r0->ru_minflt);
53259243Sobrien		break;
53359243Sobrien
53459243Sobrien	    case 'I':		/* FS blocks in	*/
53559243Sobrien		xprintf("%ld", r1->ru_inblock -	r0->ru_inblock);
53659243Sobrien		break;
53759243Sobrien
53859243Sobrien	    case 'O':		/* FS blocks out */
53959243Sobrien		xprintf("%ld", r1->ru_oublock -	r0->ru_oublock);
54059243Sobrien		break;
54159243Sobrien
54259243Sobrien# ifdef	convex
54359243Sobrien	    case 'C':			/*  CPU	parallelization	factor */
54459243Sobrien		if (r1->ru_usamples	!= 0LL)	{
54559243Sobrien		    long long parr = ((r1->ru_utotal * 100LL) /
54659243Sobrien				      r1->ru_usamples);
54759243Sobrien		    xprintf("%d.%02d", (int)(parr/100), (int)(parr%100));
54859243Sobrien		} else
54959243Sobrien		    xprintf("?");
55059243Sobrien		break;
55159243Sobrien# endif	/* convex */
55259243Sobrien	    case 'r':		/* PWP:	socket messages	recieved */
55359243Sobrien		xprintf("%ld", r1->ru_msgrcv - r0->ru_msgrcv);
55459243Sobrien		break;
55559243Sobrien
55659243Sobrien	    case 's':		/* PWP:	socket messages	sent */
55759243Sobrien		xprintf("%ld", r1->ru_msgsnd - r0->ru_msgsnd);
55859243Sobrien		break;
55959243Sobrien
56059243Sobrien	    case 'k':		/* PWP:	signals	received */
56159243Sobrien		xprintf("%ld", r1->ru_nsignals - r0->ru_nsignals);
56259243Sobrien		break;
56359243Sobrien
56459243Sobrien	    case 'w':		/* PWP:	voluntary context switches (waits) */
56559243Sobrien		xprintf("%ld", r1->ru_nvcsw - r0->ru_nvcsw);
56659243Sobrien		break;
56759243Sobrien
56859243Sobrien	    case 'c':		/* PWP:	involuntary context switches */
56959243Sobrien		xprintf("%ld", r1->ru_nivcsw - r0->ru_nivcsw);
57059243Sobrien		break;
57159243Sobrien#else /* BSDTIMES */
57259243Sobrien# ifdef	_SEQUENT_
57359243Sobrien	    case 'W':		/* number of swaps */
57459243Sobrien		i = r1->ps_swap	- r0->ps_swap;
57559243Sobrien		xprintf("%ld", i);
57659243Sobrien		break;
57759243Sobrien
57859243Sobrien	    case 'M':
57959243Sobrien		xprintf("%ld", r1->ps_maxrss / 2);
58059243Sobrien		break;
58159243Sobrien
58259243Sobrien	    case 'F':
58359243Sobrien		xprintf("%ld", r1->ps_pagein - r0->ps_pagein);
58459243Sobrien		break;
58559243Sobrien
58659243Sobrien	    case 'R':
58759243Sobrien		xprintf("%ld", r1->ps_reclaim -	r0->ps_reclaim);
58859243Sobrien		break;
58959243Sobrien
59059243Sobrien	    case 'I':
59159243Sobrien		xprintf("%ld", r1->ps_bread - r0->ps_bread);
59259243Sobrien		break;
59359243Sobrien
59459243Sobrien	    case 'O':
59559243Sobrien		xprintf("%ld", r1->ps_bwrite - r0->ps_bwrite);
59659243Sobrien		break;
59759243Sobrien
59859243Sobrien	    case 'k':
59959243Sobrien		xprintf("%ld", r1->ps_signal - r0->ps_signal);
60059243Sobrien		break;
60159243Sobrien
60259243Sobrien	    case 'w':
60359243Sobrien		xprintf("%ld", r1->ps_volcsw - r0->ps_volcsw);
60459243Sobrien		break;
60559243Sobrien
60659243Sobrien	    case 'c':
60759243Sobrien		xprintf("%ld", r1->ps_involcsw - r0->ps_involcsw);
60859243Sobrien		break;
60959243Sobrien
61059243Sobrien	    case 'Z':
61159243Sobrien		xprintf("%ld", r1->ps_zerofill - r0->ps_zerofill);
61259243Sobrien		break;
61359243Sobrien
61459243Sobrien	    case 'i':
61559243Sobrien		xprintf("%ld", r1->ps_pffincr -	r0->ps_pffincr);
61659243Sobrien		break;
61759243Sobrien
61859243Sobrien	    case 'd':
61959243Sobrien		xprintf("%ld", r1->ps_pffdecr -	r0->ps_pffdecr);
62059243Sobrien		break;
62159243Sobrien
62259243Sobrien	    case 'Y':
62359243Sobrien		xprintf("%ld", r1->ps_syscall -	r0->ps_syscall);
62459243Sobrien		break;
62559243Sobrien
62659243Sobrien	    case 'l':
62759243Sobrien		xprintf("%ld", r1->ps_lread - r0->ps_lread);
62859243Sobrien		break;
62959243Sobrien
63059243Sobrien	    case 'm':
63159243Sobrien		xprintf("%ld", r1->ps_lwrite - r0->ps_lwrite);
63259243Sobrien		break;
63359243Sobrien
63459243Sobrien	    case 'p':
63559243Sobrien		xprintf("%ld", r1->ps_phread - r0->ps_phread);
63659243Sobrien		break;
63759243Sobrien
63859243Sobrien	    case 'q':
63959243Sobrien		xprintf("%ld", r1->ps_phwrite -	r0->ps_phwrite);
64059243Sobrien		break;
64159243Sobrien# endif	/* _SEQUENT_ */
64259243Sobrien#endif /* BSDTIMES */
64359243Sobrien	    default:
64459243Sobrien		break;
64559243Sobrien	    }
64659243Sobrien    xputchar('\n');
64759243Sobrien}
64859243Sobrien
64959243Sobrien#if defined(BSDTIMES) || defined(_SEQUENT_)
65059243Sobrienstatic void
65159243Sobrienpdeltat(t1, t0)
65259243Sobrien    timeval_t *t1, *t0;
65359243Sobrien{
65459243Sobrien    timeval_t td;
65559243Sobrien
65659243Sobrien    tvsub(&td, t1, t0);
65759243Sobrien    xprintf("%ld.%03ld", td.tv_sec, td.tv_usec / 1000L);
65859243Sobrien}
65959243Sobrien
66059243Sobrienstatic void
66159243Sobrientvadd(tsum, t0)
66259243Sobrien    timeval_t *tsum, *t0;
66359243Sobrien{
66459243Sobrien
66559243Sobrien    tsum->tv_sec += t0->tv_sec;
66659243Sobrien    tsum->tv_usec += t0->tv_usec;
66759243Sobrien    if (tsum->tv_usec >= 1000000)
66859243Sobrien	tsum->tv_sec++,	tsum->tv_usec -= 1000000;
66959243Sobrien}
67059243Sobrien
67159243Sobrienvoid
67259243Sobrientvsub(tdiff, t1, t0)
67359243Sobrien    timeval_t *tdiff, *t1, *t0;
67459243Sobrien{
67559243Sobrien
67659243Sobrien    tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
67759243Sobrien    tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
67859243Sobrien    if (tdiff->tv_usec < 0)
67959243Sobrien	tdiff->tv_sec--, tdiff->tv_usec	+= 1000000;
68059243Sobrien}
68159243Sobrien
68259243Sobrien#else /* !BSDTIMES && !_SEQUENT_ */
68359243Sobrienstatic void
68459243Sobrienpdtimet(eval, bval)
68559243Sobrien#ifndef	POSIX
68659243Sobrien    time_t  eval, bval;
68759243Sobrien
68859243Sobrien#else /* POSIX */
68959243Sobrien    clock_t eval, bval;
69059243Sobrien
69159243Sobrien#endif /* POSIX	*/
69259243Sobrien{
69359243Sobrien#ifndef	POSIX
69459243Sobrien    time_t  val;
69559243Sobrien
69659243Sobrien#else /* POSIX */
69759243Sobrien    clock_t val;
69859243Sobrien
69959243Sobrien#endif /* POSIX	*/
70059243Sobrien
70159243Sobrien#ifndef	POSIX
70259243Sobrien    val	= (eval	- bval)	* 100 /	HZ;
70359243Sobrien#else /* POSIX */
70459243Sobrien    val	= (eval	- bval)	* 100 /	clk_tck;
70559243Sobrien#endif /* POSIX	*/
70659243Sobrien
70759243Sobrien    xprintf("%ld.%02ld", val / 100, val	- (val / 100 * 100));
70859243Sobrien}
70959243Sobrien#endif /* BSDTIMES || _SEQUENT_	*/
710