xref: /illumos-gate/usr/src/cmd/csh/sh.time.c (revision 258f91c6)
17c478bd9Sstevel@tonic-gate /*
26c02b4a4Smuffin  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
37c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
47c478bd9Sstevel@tonic-gate  */
57c478bd9Sstevel@tonic-gate 
67c478bd9Sstevel@tonic-gate /*	Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T	*/
77c478bd9Sstevel@tonic-gate /*	  All Rights Reserved  	*/
87c478bd9Sstevel@tonic-gate 
97c478bd9Sstevel@tonic-gate /*
107c478bd9Sstevel@tonic-gate  * Copyright (c) 1980 Regents of the University of California.
117c478bd9Sstevel@tonic-gate  * All rights reserved. The Berkeley Software License Agreement
127c478bd9Sstevel@tonic-gate  * specifies the terms and conditions for redistribution.
137c478bd9Sstevel@tonic-gate  */
147c478bd9Sstevel@tonic-gate 
157c478bd9Sstevel@tonic-gate #include "sh.h"
167c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
177c478bd9Sstevel@tonic-gate 
18*258f91c6SToomas Soome struct timeval	time0;
19*258f91c6SToomas Soome static struct rusage ru0;
20*258f91c6SToomas Soome 
217c478bd9Sstevel@tonic-gate void ruadd(struct rusage *ru, struct rusage *ru2);
227c478bd9Sstevel@tonic-gate void prusage(struct rusage *r0, struct rusage *r1, struct timeval *e,
237c478bd9Sstevel@tonic-gate 	struct timeval *b);
247c478bd9Sstevel@tonic-gate void pdeltat(struct timeval *t1, struct timeval *t0);
257c478bd9Sstevel@tonic-gate void tvadd(struct timeval *tsum, struct timeval *t0);
267c478bd9Sstevel@tonic-gate void tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0);
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * C Shell - routines handling process timing and niceing
307c478bd9Sstevel@tonic-gate  */
317c478bd9Sstevel@tonic-gate 
327c478bd9Sstevel@tonic-gate void
settimes(void)336c02b4a4Smuffin settimes(void)
347c478bd9Sstevel@tonic-gate {
357c478bd9Sstevel@tonic-gate 	struct rusage ruch;
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate #ifdef TRACE
387c478bd9Sstevel@tonic-gate 	tprintf("TRACE- settimes()\n");
397c478bd9Sstevel@tonic-gate #endif
407c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&time0, (struct timezone *)0);
417c478bd9Sstevel@tonic-gate 	(void) getrusage(RUSAGE_SELF, &ru0);
427c478bd9Sstevel@tonic-gate 	(void) getrusage(RUSAGE_CHILDREN, &ruch);
437c478bd9Sstevel@tonic-gate 	ruadd(&ru0, &ruch);
447c478bd9Sstevel@tonic-gate }
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /*
477c478bd9Sstevel@tonic-gate  * dotime is only called if it is truly a builtin function and not a
487c478bd9Sstevel@tonic-gate  * prefix to another command
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate void
dotime(void)516c02b4a4Smuffin dotime(void)
527c478bd9Sstevel@tonic-gate {
537c478bd9Sstevel@tonic-gate 	struct timeval timedol;
547c478bd9Sstevel@tonic-gate 	struct rusage ru1, ruch;
557c478bd9Sstevel@tonic-gate 
567c478bd9Sstevel@tonic-gate #ifdef TRACE
577c478bd9Sstevel@tonic-gate 	tprintf("TRACE- dotime()\n");
587c478bd9Sstevel@tonic-gate #endif
597c478bd9Sstevel@tonic-gate 	(void) getrusage(RUSAGE_SELF, &ru1);
607c478bd9Sstevel@tonic-gate 	(void) getrusage(RUSAGE_CHILDREN, &ruch);
617c478bd9Sstevel@tonic-gate 	ruadd(&ru1, &ruch);
627c478bd9Sstevel@tonic-gate 	(void) gettimeofday(&timedol, (struct timezone *)0);
637c478bd9Sstevel@tonic-gate 	prusage(&ru0, &ru1, &timedol, &time0);
647c478bd9Sstevel@tonic-gate }
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate /*
677c478bd9Sstevel@tonic-gate  * donice is only called when it's on the line by itself or with a +- value
687c478bd9Sstevel@tonic-gate  */
697c478bd9Sstevel@tonic-gate void
donice(tchar ** v)707c478bd9Sstevel@tonic-gate donice(tchar **v)
717c478bd9Sstevel@tonic-gate {
727c478bd9Sstevel@tonic-gate 	tchar *cp;
737c478bd9Sstevel@tonic-gate 	int nval;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate #ifdef TRACE
767c478bd9Sstevel@tonic-gate 	tprintf("TRACE- donice()\n");
777c478bd9Sstevel@tonic-gate #endif
787c478bd9Sstevel@tonic-gate 	v++;
797c478bd9Sstevel@tonic-gate 	cp = *v++;
807c478bd9Sstevel@tonic-gate 	if (cp == 0) {
817c478bd9Sstevel@tonic-gate 		nval = 4;
827c478bd9Sstevel@tonic-gate 	} else if (*v == 0 && (cp[0] == '+' || cp[0] == '-')) {
837c478bd9Sstevel@tonic-gate 		nval = getn(cp);
847c478bd9Sstevel@tonic-gate 	}
857c478bd9Sstevel@tonic-gate 	(void) setpriority(PRIO_PROCESS, 0, nval);
867c478bd9Sstevel@tonic-gate }
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate void
ruadd(struct rusage * ru,struct rusage * ru2)897c478bd9Sstevel@tonic-gate ruadd(struct rusage *ru, struct rusage *ru2)
907c478bd9Sstevel@tonic-gate {
917c478bd9Sstevel@tonic-gate 	long *lp, *lp2;
927c478bd9Sstevel@tonic-gate 	int cnt;
937c478bd9Sstevel@tonic-gate 	/*
947c478bd9Sstevel@tonic-gate 	 * The SunOS 4.x <sys/rusage.h> has ru_first and ru_last #defines
957c478bd9Sstevel@tonic-gate 	 * as below.
967c478bd9Sstevel@tonic-gate 	 * The SVR4/POSIX <sys/resource.h> does not have these defined for
977c478bd9Sstevel@tonic-gate 	 * struct rusage
987c478bd9Sstevel@tonic-gate 	 * The #defines below are here so that the original csh logic
997c478bd9Sstevel@tonic-gate 	 * for ruadd remains clear now that there is no longer a private copy
1007c478bd9Sstevel@tonic-gate 	 * of the old <sys/resource.h>
1017c478bd9Sstevel@tonic-gate 	 */
1027c478bd9Sstevel@tonic-gate #define	ru_first ru_ixrss
1037c478bd9Sstevel@tonic-gate #define	ru_last ru_nivcsw
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate #ifdef TRACE
1067c478bd9Sstevel@tonic-gate 	tprintf("TRACE- ruadd()\n");
1077c478bd9Sstevel@tonic-gate #endif
1087c478bd9Sstevel@tonic-gate 	tvadd(&ru->ru_utime, &ru2->ru_utime);
1097c478bd9Sstevel@tonic-gate 	tvadd(&ru->ru_stime, &ru2->ru_stime);
1107c478bd9Sstevel@tonic-gate 	if (ru2->ru_maxrss > ru->ru_maxrss) {
1117c478bd9Sstevel@tonic-gate 		ru->ru_maxrss = ru2->ru_maxrss;
1127c478bd9Sstevel@tonic-gate 	}
1137c478bd9Sstevel@tonic-gate 	cnt = &ru->ru_last - &ru->ru_first + 1;
1147c478bd9Sstevel@tonic-gate 	lp = &ru->ru_first;
1157c478bd9Sstevel@tonic-gate 	lp2 = &ru2->ru_first;
1167c478bd9Sstevel@tonic-gate 	do {
1177c478bd9Sstevel@tonic-gate 		*lp++ += *lp2++;
1187c478bd9Sstevel@tonic-gate 	} while (--cnt > 0);
1197c478bd9Sstevel@tonic-gate }
1207c478bd9Sstevel@tonic-gate 
1217c478bd9Sstevel@tonic-gate void
prusage(struct rusage * r0,struct rusage * r1,struct timeval * e,struct timeval * b)1227c478bd9Sstevel@tonic-gate prusage(struct rusage *r0, struct rusage *r1, struct timeval *e,
1237c478bd9Sstevel@tonic-gate 	struct timeval *b)
1247c478bd9Sstevel@tonic-gate {
1257c478bd9Sstevel@tonic-gate #define	pgtok(p)	((p * pgsize) / 1024)
1267c478bd9Sstevel@tonic-gate 	static int	pgsize;
1277c478bd9Sstevel@tonic-gate 
1287c478bd9Sstevel@tonic-gate 	time_t t =
1297c478bd9Sstevel@tonic-gate 	    (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 +
1307c478bd9Sstevel@tonic-gate 	    (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
1317c478bd9Sstevel@tonic-gate 	    (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 +
1327c478bd9Sstevel@tonic-gate 	    (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
1337c478bd9Sstevel@tonic-gate 	tchar *cp;
1347c478bd9Sstevel@tonic-gate 	int i;
1357c478bd9Sstevel@tonic-gate 	struct varent *vp = adrof(S_time);
1367c478bd9Sstevel@tonic-gate 	int ms =
1377c478bd9Sstevel@tonic-gate 	    (e->tv_sec - b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000;
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate #ifdef TRACE
1407c478bd9Sstevel@tonic-gate 	tprintf("TRACE- prusage()\n");
1417c478bd9Sstevel@tonic-gate #endif
1427c478bd9Sstevel@tonic-gate 	if (pgsize == 0) {
1437c478bd9Sstevel@tonic-gate 		pgsize = getpagesize();
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	cp = S_USAGEFORMAT;	/* "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww" */
1477c478bd9Sstevel@tonic-gate 	if (vp && vp->vec[0] && vp->vec[1]) {
1487c478bd9Sstevel@tonic-gate 		cp = vp->vec[1];
1497c478bd9Sstevel@tonic-gate 	}
1507c478bd9Sstevel@tonic-gate 	for (; *cp; cp++) {
1517c478bd9Sstevel@tonic-gate 		if (*cp != '%') {
1527c478bd9Sstevel@tonic-gate 			Putchar(*cp);
1537c478bd9Sstevel@tonic-gate 		} else if (cp[1]) {
1547c478bd9Sstevel@tonic-gate 			switch (*++cp) {
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 			case 'U':
1577c478bd9Sstevel@tonic-gate 				pdeltat(&r1->ru_utime, &r0->ru_utime);
1587c478bd9Sstevel@tonic-gate 				break;
1597c478bd9Sstevel@tonic-gate 
1607c478bd9Sstevel@tonic-gate 			case 'S':
1617c478bd9Sstevel@tonic-gate 				pdeltat(&r1->ru_stime, &r0->ru_stime);
1627c478bd9Sstevel@tonic-gate 				break;
1637c478bd9Sstevel@tonic-gate 
1647c478bd9Sstevel@tonic-gate 			case 'E':
1657c478bd9Sstevel@tonic-gate 				psecs_int(ms / 100);
1667c478bd9Sstevel@tonic-gate 				break;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 			case 'P':
1697c478bd9Sstevel@tonic-gate 				printf("%d%%", (int)(t * 100 /
1707c478bd9Sstevel@tonic-gate 				    ((ms ? ms : 1))));
1717c478bd9Sstevel@tonic-gate 				break;
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 			case 'W':
1747c478bd9Sstevel@tonic-gate 				i = r1->ru_nswap - r0->ru_nswap;
1757c478bd9Sstevel@tonic-gate 				printf("%d", i);
1767c478bd9Sstevel@tonic-gate 				break;
1777c478bd9Sstevel@tonic-gate 
1787c478bd9Sstevel@tonic-gate 			case 'X':
1797c478bd9Sstevel@tonic-gate 				printf("%d", t == 0 ? 0 :
1807c478bd9Sstevel@tonic-gate 				    pgtok((r1->ru_ixrss - r0->ru_ixrss) / t));
1817c478bd9Sstevel@tonic-gate 				break;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate 			case 'D':
1847c478bd9Sstevel@tonic-gate 				printf("%d", t == 0 ? 0 :
1857c478bd9Sstevel@tonic-gate 				    pgtok((r1->ru_idrss + r1->ru_isrss-
1867c478bd9Sstevel@tonic-gate 				    (r0->ru_idrss + r0->ru_isrss)) / t));
1877c478bd9Sstevel@tonic-gate 				break;
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 			case 'K':
1907c478bd9Sstevel@tonic-gate 				printf("%d", t == 0 ? 0 :
1917c478bd9Sstevel@tonic-gate 				    pgtok(((r1->ru_ixrss + r1->ru_isrss +
1927c478bd9Sstevel@tonic-gate 				    r1->ru_idrss) - (r0->ru_ixrss +
1937c478bd9Sstevel@tonic-gate 				    r0->ru_idrss + r0->ru_isrss)) / t));
1947c478bd9Sstevel@tonic-gate 				break;
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 			case 'M':
1977c478bd9Sstevel@tonic-gate 				printf("%d", r1->ru_maxrss / 2);
1987c478bd9Sstevel@tonic-gate 				break;
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 			case 'F':
2017c478bd9Sstevel@tonic-gate 				printf("%d", r1->ru_majflt - r0->ru_majflt);
2027c478bd9Sstevel@tonic-gate 				break;
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 			case 'R':
2057c478bd9Sstevel@tonic-gate 				printf("%d", r1->ru_minflt - r0->ru_minflt);
2067c478bd9Sstevel@tonic-gate 				break;
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 			case 'I':
2097c478bd9Sstevel@tonic-gate 				printf("%d", r1->ru_inblock - r0->ru_inblock);
2107c478bd9Sstevel@tonic-gate 				break;
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate 			case 'O':
2137c478bd9Sstevel@tonic-gate 				printf("%d", r1->ru_oublock - r0->ru_oublock);
2147c478bd9Sstevel@tonic-gate 				break;
2157c478bd9Sstevel@tonic-gate 			}
2167c478bd9Sstevel@tonic-gate 		}
2177c478bd9Sstevel@tonic-gate 	}
2187c478bd9Sstevel@tonic-gate 	Putchar('\n');
2197c478bd9Sstevel@tonic-gate #undef	pgtok
2207c478bd9Sstevel@tonic-gate }
2217c478bd9Sstevel@tonic-gate 
2227c478bd9Sstevel@tonic-gate void
pdeltat(struct timeval * t1,struct timeval * t0)2237c478bd9Sstevel@tonic-gate pdeltat(struct timeval *t1, struct timeval *t0)
2247c478bd9Sstevel@tonic-gate {
2257c478bd9Sstevel@tonic-gate 	struct timeval td;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate #ifdef TRACE
2287c478bd9Sstevel@tonic-gate 	tprintf("TRACE- pdeltat()\n");
2297c478bd9Sstevel@tonic-gate #endif
2307c478bd9Sstevel@tonic-gate 	tvsub(&td, t1, t0);
2317c478bd9Sstevel@tonic-gate 	/* change printf formats */
2327c478bd9Sstevel@tonic-gate 	printf("%d.%01d", td.tv_sec, td.tv_usec / 100000);
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate void
tvadd(struct timeval * tsum,struct timeval * t0)2367c478bd9Sstevel@tonic-gate tvadd(struct timeval *tsum, struct timeval *t0)
2377c478bd9Sstevel@tonic-gate {
2387c478bd9Sstevel@tonic-gate 
2397c478bd9Sstevel@tonic-gate #ifdef TRACE
2407c478bd9Sstevel@tonic-gate 	tprintf("TRACE- tvadd()\n");
2417c478bd9Sstevel@tonic-gate #endif
2427c478bd9Sstevel@tonic-gate 	tsum->tv_sec += t0->tv_sec;
2437c478bd9Sstevel@tonic-gate 	tsum->tv_usec += t0->tv_usec;
2447c478bd9Sstevel@tonic-gate 	if (tsum->tv_usec > 1000000) {
2457c478bd9Sstevel@tonic-gate 		tsum->tv_sec++;
2467c478bd9Sstevel@tonic-gate 		tsum->tv_usec -= 1000000;
2477c478bd9Sstevel@tonic-gate 	}
2487c478bd9Sstevel@tonic-gate }
2497c478bd9Sstevel@tonic-gate 
2507c478bd9Sstevel@tonic-gate void
tvsub(struct timeval * tdiff,struct timeval * t1,struct timeval * t0)2517c478bd9Sstevel@tonic-gate tvsub(struct timeval *tdiff, struct timeval *t1, struct timeval *t0)
2527c478bd9Sstevel@tonic-gate {
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate #ifdef TRACE
2557c478bd9Sstevel@tonic-gate 	tprintf("TRACE- tvsub()\n");
2567c478bd9Sstevel@tonic-gate #endif
2577c478bd9Sstevel@tonic-gate 	tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
2587c478bd9Sstevel@tonic-gate 	tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
2597c478bd9Sstevel@tonic-gate 	if (tdiff->tv_usec < 0) {
2607c478bd9Sstevel@tonic-gate 		tdiff->tv_sec--;
2617c478bd9Sstevel@tonic-gate 		tdiff->tv_usec += 1000000;
2627c478bd9Sstevel@tonic-gate 	}
2637c478bd9Sstevel@tonic-gate }
264