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