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