1232633Smp/* $Header: /p/tcsh/cvsroot/tcsh/sh.time.c,v 3.35 2010/12/09 15:39:29 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
35232633SmpRCSID("$tcsh: sh.time.c,v 3.35 2010/12/09 15:39:29 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
55167465Smpstatic	void	pdtimet	(clock_t, clock_t);
5659243Sobrien# else /* ! POSIX */
57167465Smpstatic	void	pdtimet	(time_t, time_t);
5859243Sobrien# endif	/* ! POSIX */
5959243Sobrien#else /* BSDTIMES || _SEQUENT_ */
60167465Smpstatic	void	tvadd	(timeval_t *, timeval_t *);
61167465Smpstatic	void	pdeltat	(timeval_t *, timeval_t *);
6259243Sobrien#endif /* BSDTIMES || _SEQUENT_	*/
6359243Sobrien
6459243Sobrienvoid
65167465Smpsettimes(void)
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    time0 = times(&times0);
8759243Sobrien    times0.tms_stime +=	times0.tms_cstime;
8859243Sobrien    times0.tms_utime +=	times0.tms_cutime;
8959243Sobrien    times0.tms_cstime =	0;
9059243Sobrien    times0.tms_cutime =	0;
9159243Sobrien# endif	/* _SEQUENT_ */
9259243Sobrien#endif /* BSDTIMES */
9359243Sobrien}
9459243Sobrien
9559243Sobrien/*
9659243Sobrien * dotime is only called if it is truly	a builtin function and not a
9759243Sobrien * prefix to another command
9859243Sobrien */
9959243Sobrien/*ARGSUSED*/
10059243Sobrienvoid
101167465Smpdotime(Char **v, struct command *c)
10259243Sobrien{
10359243Sobrien#ifdef BSDTIMES
10459243Sobrien    timeval_t timedol;
10559243Sobrien    struct sysrusage ru1, ruch;
10659243Sobrien#ifdef convex
10759243Sobrien    memset(&ru1, 0, sizeof(ru1));
10859243Sobrien    memset(&ruch, 0, sizeof(ruch));
10959243Sobrien#endif /* convex */
11059243Sobrien
11159243Sobrien    (void) getrusage(RUSAGE_SELF, (struct rusage *) &ru1);
11259243Sobrien    (void) getrusage(RUSAGE_CHILDREN, (struct rusage *) &ruch);
11359243Sobrien    ruadd(&ru1,	&ruch);
11459243Sobrien    (void) gettimeofday(&timedol, NULL);
11559243Sobrien    prusage(&ru0, &ru1,	&timedol, &time0);
11659243Sobrien#else
11759243Sobrien# ifdef	_SEQUENT_
11859243Sobrien    timeval_t timedol;
11959243Sobrien    struct process_stats ru1, ruch;
12059243Sobrien
12159243Sobrien    (void) get_process_stats(&timedol, PS_SELF,	&ru1, &ruch);
12259243Sobrien    ruadd(&ru1,	&ruch);
12359243Sobrien    prusage(&ru0, &ru1,	&timedol, &time0);
12459243Sobrien# else /* _SEQUENT_ */
12559243Sobrien#  ifndef POSIX
12659243Sobrien    time_t  timedol;
12759243Sobrien#  else	/* POSIX */
12859243Sobrien    clock_t timedol;
12959243Sobrien#  endif /* POSIX */
13059243Sobrien
13159243Sobrien    struct tms times_dol;
13259243Sobrien
13359243Sobrien    timedol = times(&times_dol);
13459243Sobrien    times_dol.tms_stime	+= times_dol.tms_cstime;
13559243Sobrien    times_dol.tms_utime	+= times_dol.tms_cutime;
13659243Sobrien    times_dol.tms_cstime = 0;
13759243Sobrien    times_dol.tms_cutime = 0;
13859243Sobrien    prusage(&times0, &times_dol, timedol, time0);
13959243Sobrien# endif	/* _SEQUENT_ */
14059243Sobrien#endif /* BSDTIMES */
14159243Sobrien    USE(c);
14259243Sobrien    USE(v);
14359243Sobrien}
14459243Sobrien
14559243Sobrien/*
14659243Sobrien * donice is only called when it on the	line by	itself or with a +- value
14759243Sobrien */
14859243Sobrien/*ARGSUSED*/
14959243Sobrienvoid
150167465Smpdonice(Char **v, struct command *c)
15159243Sobrien{
152145479Smp    Char *cp;
15359243Sobrien    int	    nval = 0;
15459243Sobrien
15559243Sobrien    USE(c);
15659243Sobrien    v++, cp = *v++;
15759243Sobrien    if (cp == 0)
15859243Sobrien	nval = 4;
15959243Sobrien    else if (*v	== 0 &&	any("+-", cp[0]))
16059243Sobrien	nval = getn(cp);
161145479Smp#ifdef HAVE_SETPRIORITY
16283098Smp    if (setpriority(PRIO_PROCESS, 0, nval) == -1 && errno)
16383098Smp	stderror(ERR_SYSTEM, "setpriority", strerror(errno));
164145479Smp#else /* !HAVE_SETPRIORITY */
16559243Sobrien    (void) nice(nval);
166145479Smp#endif /* HAVE_SETPRIORITY */
16759243Sobrien}
16859243Sobrien
16959243Sobrien#ifdef BSDTIMES
17059243Sobrienvoid
171167465Smpruadd(struct sysrusage *ru, struct sysrusage *ru2)
17259243Sobrien{
17359243Sobrien    tvadd(&ru->ru_utime, &ru2->ru_utime);
17459243Sobrien    tvadd(&ru->ru_stime, &ru2->ru_stime);
175145479Smp#ifndef _OSD_POSIX
17659243Sobrien    if (ru2->ru_maxrss > ru->ru_maxrss)
17759243Sobrien	ru->ru_maxrss =	ru2->ru_maxrss;
17859243Sobrien
17959243Sobrien    ru->ru_ixrss += ru2->ru_ixrss;
18059243Sobrien    ru->ru_idrss += ru2->ru_idrss;
18159243Sobrien    ru->ru_isrss += ru2->ru_isrss;
18259243Sobrien    ru->ru_minflt += ru2->ru_minflt;
18359243Sobrien    ru->ru_majflt += ru2->ru_majflt;
18459243Sobrien    ru->ru_nswap += ru2->ru_nswap;
18559243Sobrien    ru->ru_inblock += ru2->ru_inblock;
18659243Sobrien    ru->ru_oublock += ru2->ru_oublock;
18759243Sobrien    ru->ru_msgsnd += ru2->ru_msgsnd;
18859243Sobrien    ru->ru_msgrcv += ru2->ru_msgrcv;
18959243Sobrien    ru->ru_nsignals += ru2->ru_nsignals;
19059243Sobrien    ru->ru_nvcsw += ru2->ru_nvcsw;
19159243Sobrien    ru->ru_nivcsw += ru2->ru_nivcsw;
192145479Smp#endif /*bs2000*/
19359243Sobrien
19459243Sobrien# ifdef	convex
19559243Sobrien    tvadd(&ru->ru_exutime, &ru2->ru_exutime);
19659243Sobrien    ru->ru_utotal += ru2->ru_utotal;
19759243Sobrien    ru->ru_usamples += ru2->ru_usamples;
19859243Sobrien    ru->ru_stotal += ru2->ru_stotal;
19959243Sobrien    ru->ru_ssamples += ru2->ru_ssamples;
20059243Sobrien# endif	/* convex */
20159243Sobrien}
20259243Sobrien
20359243Sobrien#else /* BSDTIMES */
20459243Sobrien# ifdef	_SEQUENT_
20559243Sobrienvoid
206167465Smpruadd(struct process_stats *ru, struct process_stats *ru2)
20759243Sobrien{
20859243Sobrien    tvadd(&ru->ps_utime, &ru2->ps_utime);
20959243Sobrien    tvadd(&ru->ps_stime, &ru2->ps_stime);
21059243Sobrien    if (ru2->ps_maxrss > ru->ps_maxrss)
21159243Sobrien	ru->ps_maxrss =	ru2->ps_maxrss;
21259243Sobrien
21359243Sobrien    ru->ps_pagein += ru2->ps_pagein;
21459243Sobrien    ru->ps_reclaim += ru2->ps_reclaim;
21559243Sobrien    ru->ps_zerofill += ru2->ps_zerofill;
21659243Sobrien    ru->ps_pffincr += ru2->ps_pffincr;
21759243Sobrien    ru->ps_pffdecr += ru2->ps_pffdecr;
21859243Sobrien    ru->ps_swap	+= ru2->ps_swap;
21959243Sobrien    ru->ps_syscall += ru2->ps_syscall;
22059243Sobrien    ru->ps_volcsw += ru2->ps_volcsw;
22159243Sobrien    ru->ps_involcsw += ru2->ps_involcsw;
22259243Sobrien    ru->ps_signal += ru2->ps_signal;
22359243Sobrien    ru->ps_lread += ru2->ps_lread;
22459243Sobrien    ru->ps_lwrite += ru2->ps_lwrite;
22559243Sobrien    ru->ps_bread += ru2->ps_bread;
22659243Sobrien    ru->ps_bwrite += ru2->ps_bwrite;
22759243Sobrien    ru->ps_phread += ru2->ps_phread;
22859243Sobrien    ru->ps_phwrite += ru2->ps_phwrite;
22959243Sobrien}
23059243Sobrien
23159243Sobrien# endif	/* _SEQUENT_ */
23259243Sobrien#endif /* BSDTIMES */
23359243Sobrien
23459243Sobrien#ifdef BSDTIMES
23559243Sobrien
23659243Sobrien/*
23759243Sobrien * PWP:	the LOG1024 and	pagetok	stuff taken from the top command,
23859243Sobrien * written by William LeFebvre
23959243Sobrien */
24059243Sobrien/* Log base 2 of 1024 is 10 (2^10 == 1024) */
24159243Sobrien#define	LOG1024		10
24259243Sobrien
24359243Sobrien/* Convert clicks (kernel pages) to kbytes ... */
24459243Sobrien/* If there is no PGSHIFT defined, assume it is	11 */
24559243Sobrien/* Is this needed for compatability with some old flavor of 4.2	or 4.1?	*/
24659243Sobrien#ifdef SUNOS4
24759243Sobrien# ifndef PGSHIFT
24859243Sobrien#  define pagetok(size)	  ((size) << 1)
24959243Sobrien# else
25059243Sobrien#  if PGSHIFT>10
25159243Sobrien#   define pagetok(size)   ((size) << (PGSHIFT - LOG1024))
25259243Sobrien#  else
25359243Sobrien#   define pagetok(size)   ((size) >> (LOG1024 - PGSHIFT))
25459243Sobrien#  endif
25559243Sobrien# endif
25659243Sobrien#endif
25759243Sobrien
25859243Sobrien/*
25959243Sobrien * if any other	machines return	wierd values in	the ru_i* stuff, put
26059243Sobrien * the adjusting macro here:
26159243Sobrien */
26259243Sobrien#ifdef SUNOS4
26359243Sobrien# define IADJUST(i)	(pagetok(i)/2)
26459243Sobrien#else /* SUNOS4	*/
26559243Sobrien# ifdef	convex
26659243Sobrien   /*
26759243Sobrien    * convex has megabytes * CLK_TCK
26859243Sobrien    * multiply by 100 since we use time	in 100ths of a second in prusage
26959243Sobrien    */
27059243Sobrien#  define IADJUST(i) (((i) << 10) / CLK_TCK * 100)
27159243Sobrien# else /* convex */
27259243Sobrien#  define IADJUST(i)	(i)
27359243Sobrien# endif	/* convex */
27459243Sobrien#endif /* SUNOS4 */
27559243Sobrien
27659243Sobrienvoid
277167465Smpprusage(struct sysrusage *r0, struct sysrusage *r1, timeval_t *e, timeval_t *b)
27859243Sobrien
27959243Sobrien#else /* BSDTIMES */
28059243Sobrien# ifdef	_SEQUENT_
28159243Sobrienvoid
282167465Smpprusage(struct process_stats *r0, struct process_stats *r1, timeval_t e,
283167465Smp	timeval_t b)
28459243Sobrien
28559243Sobrien# else /* _SEQUENT_ */
286167465Smp#  ifndef POSIX
28759243Sobrienvoid
288167465Smpprusage(struct tms *bs, struct tms *es, time_t e, time_t b)
28959243Sobrien#  else	/* POSIX */
290167465Smpvoid
291167465Smpprusage(struct tms *bs, struct tms *es, clock_t e, clock_t b)
29259243Sobrien#  endif /* POSIX */
29359243Sobrien# endif	/* _SEQUENT_ */
29459243Sobrien#endif /* BSDTIMES */
29559243Sobrien{
29659243Sobrien#ifdef BSDTIMES
297145479Smp    time_t t =
29859243Sobrien    (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec)	* 100 +
29959243Sobrien    (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
30059243Sobrien    (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec)	* 100 +
30159243Sobrien    (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
30259243Sobrien
30359243Sobrien#else
30459243Sobrien# ifdef	_SEQUENT_
305145479Smp    time_t t =
30659243Sobrien    (r1->ps_utime.tv_sec - r0->ps_utime.tv_sec)	* 100 +
30759243Sobrien    (r1->ps_utime.tv_usec - r0->ps_utime.tv_usec) / 10000 +
30859243Sobrien    (r1->ps_stime.tv_sec - r0->ps_stime.tv_sec)	* 100 +
30959243Sobrien    (r1->ps_stime.tv_usec - r0->ps_stime.tv_usec) / 10000;
31059243Sobrien
31159243Sobrien# else /* _SEQUENT_ */
31259243Sobrien#  ifndef POSIX
313145479Smp    time_t t =	(es->tms_utime - bs->tms_utime +
31459243Sobrien			 es->tms_stime - bs->tms_stime)	* 100 /	HZ;
31559243Sobrien
31659243Sobrien#  else	/* POSIX */
317145479Smp    clock_t t = (es->tms_utime	- bs->tms_utime	+
31859243Sobrien			  es->tms_stime	- bs->tms_stime) * 100 / clk_tck;
31959243Sobrien
32059243Sobrien#  endif /* POSIX */
32159243Sobrien# endif	/* _SEQUENT_ */
32259243Sobrien#endif /* BSDTIMES */
32359243Sobrien
324145479Smp    const char *cp;
325145479Smp    long i;
326145479Smp    struct varent *vp = adrof(STRtime);
32759243Sobrien
32859243Sobrien#ifdef BSDTIMES
32959243Sobrien# ifdef	convex
33059243Sobrien    static struct system_information sysinfo;
33159243Sobrien    long long memtmp;	/* let memory calculations exceede 2Gb */
33259243Sobrien# endif	/* convex */
33359243Sobrien    int	    ms = (int)
33459243Sobrien    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
33559243Sobrien
33659243Sobrien    cp = "%Uu %Ss %E %P	%X+%Dk %I+%Oio %Fpf+%Ww";
33759243Sobrien#else /* !BSDTIMES */
33859243Sobrien# ifdef	_SEQUENT_
33959243Sobrien    int	    ms = (int)
34059243Sobrien    ((e->tv_sec	- b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000);
34159243Sobrien
34259243Sobrien    cp = "%Uu %Ss %E %P	%I+%Oio	%Fpf+%Ww";
34359243Sobrien# else /* !_SEQUENT_ */
34459243Sobrien#  ifndef POSIX
34559243Sobrien    time_t ms = ((time_t)((e - b) / HZ) * 100) +
34659243Sobrien		 (time_t)(((e - b) % HZ) * 100) / HZ;
34759243Sobrien#  else	/* POSIX */
34859243Sobrien    clock_t ms = ((clock_t)((e - b) / clk_tck) * 100) +
34959243Sobrien		  (clock_t)(((e - b) % clk_tck) * 100) / clk_tck;
35059243Sobrien#  endif /* POSIX */
35159243Sobrien
35259243Sobrien    cp = "%Uu %Ss %E %P";
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",
369232633Smp	    (unsigned long)es->tms_utime, (unsigned long)bs->tms_utime);
37059243Sobrien    xprintf("es->tms_stime %lu bs->tms_stime %lu\n",
371232633Smp	    (unsigned long)es->tms_stime, (unsigned long)bs->tms_stime);
372232633Smp    xprintf("ms	%llu e %p b %p\n", (unsigned long long)ms, e, b);
373232633Smp    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
483232633Smp		xprintf("%lld", (long long)(t == 0 ?	0L :
484232633Smp			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
492232633Smp		xprintf("%lld", (long long)(t == 0 ?	0L :
49359243Sobrien			IADJUST(r1->ru_idrss + r1->ru_isrss -
494232633Smp				(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
502232633Smp		xprintf("%lld", (long long)(t == 0 ? 0L :
50359243Sobrien			IADJUST((r1->ru_ixrss +	r1->ru_isrss + r1->ru_idrss) -
504232633Smp			   (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
510232633Smp		xprintf("%ld", (long)pagetok(r1->ru_maxrss));
51159243Sobrien#else
51259243Sobrien# ifdef	convex
513232633Smp		xprintf("%ld", (long)(r1->ru_maxrss * 4L));
51459243Sobrien# else /* !convex */
515145479Smp#  ifdef _OSD_POSIX
516145479Smp		xprintf("0",0);
517145479Smp#  else
518232633Smp		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
528232633Smp		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
536232633Smp		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
544232633Smp		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
552232633Smp		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
570232633Smp		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
578232633Smp		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
586232633Smp		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
594232633Smp		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
602232633Smp		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;
609232633Smp		xprintf("%ld", (long)i);
61059243Sobrien		break;
61159243Sobrien
61259243Sobrien	    case 'M':
613232633Smp		xprintf("%ld", (long)r1->ps_maxrss);
61459243Sobrien		break;
61559243Sobrien
61659243Sobrien	    case 'F':
617232633Smp		xprintf("%ld", (long)(r1->ps_pagein - r0->ps_pagein));
61859243Sobrien		break;
61959243Sobrien
62059243Sobrien	    case 'R':
621232633Smp		xprintf("%ld", (long)(r1->ps_reclaim -	r0->ps_reclaim));
62259243Sobrien		break;
62359243Sobrien
62459243Sobrien	    case 'I':
625232633Smp		xprintf("%ld", (long)(r1->ps_bread - r0->ps_bread));
62659243Sobrien		break;
62759243Sobrien
62859243Sobrien	    case 'O':
629232633Smp		xprintf("%ld", (long)(r1->ps_bwrite - r0->ps_bwrite));
63059243Sobrien		break;
63159243Sobrien
63259243Sobrien	    case 'k':
633232633Smp		xprintf("%ld", (long)(r1->ps_signal - r0->ps_signal));
63459243Sobrien		break;
63559243Sobrien
63659243Sobrien	    case 'w':
637232633Smp		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':
645232633Smp		xprintf("%ld", (long)(r1->ps_zerofill - r0->ps_zerofill));
64659243Sobrien		break;
64759243Sobrien
64859243Sobrien	    case 'i':
649232633Smp		xprintf("%ld", (long)(r1->ps_pffincr - r0->ps_pffincr));
65059243Sobrien		break;
65159243Sobrien
65259243Sobrien	    case 'd':
653232633Smp		xprintf("%ld", (long)(r1->ps_pffdecr - r0->ps_pffdecr));
65459243Sobrien		break;
65559243Sobrien
65659243Sobrien	    case 'Y':
657232633Smp		xprintf("%ld", (long)(r1->ps_syscall - r0->ps_syscall));
65859243Sobrien		break;
65959243Sobrien
66059243Sobrien	    case 'l':
661232633Smp		xprintf("%ld", (long)(r1->ps_lread - r0->ps_lread));
66259243Sobrien		break;
66359243Sobrien
66459243Sobrien	    case 'm':
665232633Smp		xprintf("%ld", (long)(r1->ps_lwrite - r0->ps_lwrite));
66659243Sobrien		break;
66759243Sobrien
66859243Sobrien	    case 'p':
669232633Smp		xprintf("%ld", (long)(r1->ps_phread - r0->ps_phread));
67059243Sobrien		break;
67159243Sobrien
67259243Sobrien	    case 'q':
673232633Smp		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');
68159243Sobrien}
68259243Sobrien
68359243Sobrien#if defined(BSDTIMES) || defined(_SEQUENT_)
68459243Sobrienstatic void
685167465Smppdeltat(timeval_t *t1, timeval_t *t0)
68659243Sobrien{
68759243Sobrien    timeval_t td;
68859243Sobrien
68959243Sobrien    tvsub(&td, t1, t0);
690232633Smp    xprintf("%lld.%03ld", (long long)td.tv_sec, (long)td.tv_usec / 1000L);
69159243Sobrien}
69259243Sobrien
69359243Sobrienstatic void
694167465Smptvadd(timeval_t *tsum, timeval_t *t0)
69559243Sobrien{
69659243Sobrien
69759243Sobrien    tsum->tv_sec += t0->tv_sec;
69859243Sobrien    tsum->tv_usec += t0->tv_usec;
69959243Sobrien    if (tsum->tv_usec >= 1000000)
70059243Sobrien	tsum->tv_sec++,	tsum->tv_usec -= 1000000;
70159243Sobrien}
70259243Sobrien
70359243Sobrienvoid
704167465Smptvsub(timeval_t *tdiff, timeval_t *t1, timeval_t *t0)
70559243Sobrien{
70659243Sobrien
70759243Sobrien    tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
70859243Sobrien    tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
70959243Sobrien    if (tdiff->tv_usec < 0)
71059243Sobrien	tdiff->tv_sec--, tdiff->tv_usec	+= 1000000;
71159243Sobrien}
71259243Sobrien
71359243Sobrien#else /* !BSDTIMES && !_SEQUENT_ */
71459243Sobrienstatic void
71559243Sobrien#ifndef	POSIX
716167465Smppdtimet(time_t eval, time_t bval)
71759243Sobrien
71859243Sobrien#else /* POSIX */
719167465Smppdtimet(clock_t eval, clock_t bval)
72059243Sobrien
72159243Sobrien#endif /* POSIX	*/
72259243Sobrien{
72359243Sobrien#ifndef	POSIX
72459243Sobrien    time_t  val;
72559243Sobrien
72659243Sobrien#else /* POSIX */
72759243Sobrien    clock_t val;
72859243Sobrien
72959243Sobrien#endif /* POSIX	*/
73059243Sobrien
73159243Sobrien#ifndef	POSIX
73259243Sobrien    val	= (eval	- bval)	* 100 /	HZ;
73359243Sobrien#else /* POSIX */
73459243Sobrien    val	= (eval	- bval)	* 100 /	clk_tck;
73559243Sobrien#endif /* POSIX	*/
73659243Sobrien
737232633Smp    xprintf("%lld.%02ld", (long long)(val / 100),
738232633Smp	(long long)(val - (val / 100 * 100)));
73959243Sobrien}
74059243Sobrien#endif /* BSDTIMES || _SEQUENT_	*/
741