Home | History | Annotate | Line # | Download | only in csh
time.c revision 1.15
      1 /* $NetBSD: time.c,v 1.15 2005/06/26 19:10:48 christos Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 1980, 1991, 1993
      5  *	The Regents of the University of California.  All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. Neither the name of the University nor the names of its contributors
     16  *    may be used to endorse or promote products derived from this software
     17  *    without specific prior written permission.
     18  *
     19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     29  * SUCH DAMAGE.
     30  */
     31 
     32 #include <sys/cdefs.h>
     33 #ifndef lint
     34 #if 0
     35 static char sccsid[] = "@(#)time.c	8.1 (Berkeley) 5/31/93";
     36 #else
     37 __RCSID("$NetBSD: time.c,v 1.15 2005/06/26 19:10:48 christos Exp $");
     38 #endif
     39 #endif /* not lint */
     40 
     41 #include <sys/types.h>
     42 
     43 #include <stdarg.h>
     44 
     45 #include "csh.h"
     46 #include "extern.h"
     47 
     48 /*
     49  * C Shell - routines handling process timing and niceing
     50  */
     51 static void pdeltat(struct timeval *, struct timeval *);
     52 extern char *strpct(u_long num, u_long denom, u_int digits);
     53 
     54 void
     55 settimes(void)
     56 {
     57     struct rusage ruch;
     58 
     59     (void)gettimeofday(&time0, NULL);
     60     (void)getrusage(RUSAGE_SELF, &ru0);
     61     (void)getrusage(RUSAGE_CHILDREN, &ruch);
     62     ruadd(&ru0, &ruch);
     63 }
     64 
     65 /*
     66  * dotime is only called if it is truly a builtin function and not a
     67  * prefix to another command
     68  */
     69 void
     70 /*ARGSUSED*/
     71 dotime(Char **v, struct command *t)
     72 {
     73     struct rusage ru1, ruch;
     74     struct timeval timedol;
     75 
     76     (void)getrusage(RUSAGE_SELF, &ru1);
     77     (void)getrusage(RUSAGE_CHILDREN, &ruch);
     78     ruadd(&ru1, &ruch);
     79     (void)gettimeofday(&timedol, NULL);
     80     prusage(&ru0, &ru1, &timedol, &time0);
     81 }
     82 
     83 /*
     84  * donice is only called when it on the line by itself or with a +- value
     85  */
     86 void
     87 /*ARGSUSED*/
     88 donice(Char **v, struct command *t)
     89 {
     90     Char *cp;
     91     int nval;
     92 
     93     nval = 0;
     94     v++;
     95     cp = *v++;
     96     if (cp == 0)
     97 	nval = 4;
     98     else if (*v == 0 && any("+-", cp[0]))
     99 	nval = getn(cp);
    100     (void)setpriority(PRIO_PROCESS, 0, nval);
    101 }
    102 
    103 void
    104 ruadd(struct rusage *ru, struct rusage *ru2)
    105 {
    106     timeradd(&ru->ru_utime, &ru2->ru_utime, &ru->ru_utime);
    107     timeradd(&ru->ru_stime, &ru2->ru_stime, &ru->ru_stime);
    108     if (ru2->ru_maxrss > ru->ru_maxrss)
    109 	ru->ru_maxrss = ru2->ru_maxrss;
    110 
    111     ru->ru_ixrss += ru2->ru_ixrss;
    112     ru->ru_idrss += ru2->ru_idrss;
    113     ru->ru_isrss += ru2->ru_isrss;
    114     ru->ru_minflt += ru2->ru_minflt;
    115     ru->ru_majflt += ru2->ru_majflt;
    116     ru->ru_nswap += ru2->ru_nswap;
    117     ru->ru_inblock += ru2->ru_inblock;
    118     ru->ru_oublock += ru2->ru_oublock;
    119     ru->ru_msgsnd += ru2->ru_msgsnd;
    120     ru->ru_msgrcv += ru2->ru_msgrcv;
    121     ru->ru_nsignals += ru2->ru_nsignals;
    122     ru->ru_nvcsw += ru2->ru_nvcsw;
    123     ru->ru_nivcsw += ru2->ru_nivcsw;
    124 }
    125 
    126 void
    127 prusage(struct rusage *r0, struct rusage *r1, struct timeval *e,
    128         struct timeval *b)
    129 {
    130     struct varent *vp;
    131     const char *cp;
    132     long i;
    133     time_t t;
    134     int ms;
    135 
    136     cp = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww";
    137     ms = (e->tv_sec - b->tv_sec) * 100 + (e->tv_usec - b->tv_usec) / 10000;
    138     t = (r1->ru_utime.tv_sec - r0->ru_utime.tv_sec) * 100 +
    139         (r1->ru_utime.tv_usec - r0->ru_utime.tv_usec) / 10000 +
    140         (r1->ru_stime.tv_sec - r0->ru_stime.tv_sec) * 100 +
    141         (r1->ru_stime.tv_usec - r0->ru_stime.tv_usec) / 10000;
    142     vp = adrof(STRtime);
    143 
    144     if (vp && vp->vec[0] && vp->vec[1])
    145 	cp = short2str(vp->vec[1]);
    146 
    147     for (; *cp; cp++)
    148 	if (*cp != '%')
    149 	    (void) fputc(*cp, cshout);
    150 	else if (cp[1])
    151 	    switch (*++cp) {
    152 	    case 'D':		/* (average) unshared data size */
    153 		(void)fprintf(cshout, "%ld", t == 0 ? 0L :
    154 			(r1->ru_idrss + r1->ru_isrss -
    155 			 (r0->ru_idrss + r0->ru_isrss)) / t);
    156 		break;
    157 	    case 'E':		/* elapsed (wall-clock) time */
    158 		pcsecs((long) ms);
    159 		break;
    160 	    case 'F':		/* page faults */
    161 		(void)fprintf(cshout, "%ld", r1->ru_majflt - r0->ru_majflt);
    162 		break;
    163 	    case 'I':		/* FS blocks in */
    164 		(void)fprintf(cshout, "%ld", r1->ru_inblock - r0->ru_inblock);
    165 		break;
    166 	    case 'K':		/* (average) total data memory used  */
    167 		(void)fprintf(cshout, "%ld", t == 0 ? 0L :
    168 			((r1->ru_ixrss + r1->ru_isrss + r1->ru_idrss) -
    169 			 (r0->ru_ixrss + r0->ru_idrss + r0->ru_isrss)) / t);
    170 		break;
    171 	    case 'M':		/* max. Resident Set Size */
    172 		(void)fprintf(cshout, "%ld", r1->ru_maxrss / 2L);
    173 		break;
    174 	    case 'O':		/* FS blocks out */
    175 		(void)fprintf(cshout, "%ld", r1->ru_oublock - r0->ru_oublock);
    176 		break;
    177 	    case 'P':		/* percent time spent running */
    178 		/* check if it did not run at all */
    179 		if (ms == 0) {
    180 			(void)fputs("0.0%", cshout);
    181 		} else {
    182 			(void)fputs(strpct((ulong)t, (ulong)ms, 1), cshout);
    183 		}
    184 		break;
    185 	    case 'R':		/* page reclaims */
    186 		(void)fprintf(cshout, "%ld", r1->ru_minflt - r0->ru_minflt);
    187 		break;
    188 	    case 'S':		/* system CPU time used */
    189 		pdeltat(&r1->ru_stime, &r0->ru_stime);
    190 		break;
    191 	    case 'U':		/* user CPU time used */
    192 		pdeltat(&r1->ru_utime, &r0->ru_utime);
    193 		break;
    194 	    case 'W':		/* number of swaps */
    195 		i = r1->ru_nswap - r0->ru_nswap;
    196 		(void)fprintf(cshout, "%ld", i);
    197 		break;
    198 	    case 'X':		/* (average) shared text size */
    199 		(void)fprintf(cshout, "%ld", t == 0 ? 0L :
    200 			       (r1->ru_ixrss - r0->ru_ixrss) / t);
    201 		break;
    202 	    case 'c':		/* num. involuntary context switches */
    203 		(void)fprintf(cshout, "%ld", r1->ru_nivcsw - r0->ru_nivcsw);
    204 		break;
    205 	    case 'k':		/* number of signals received */
    206 		(void)fprintf(cshout, "%ld", r1->ru_nsignals-r0->ru_nsignals);
    207 		break;
    208 	    case 'r':		/* socket messages received */
    209 		(void)fprintf(cshout, "%ld", r1->ru_msgrcv - r0->ru_msgrcv);
    210 		break;
    211 	    case 's':		/* socket messages sent */
    212 		(void)fprintf(cshout, "%ld", r1->ru_msgsnd - r0->ru_msgsnd);
    213 		break;
    214 	    case 'w':		/* num. voluntary context switches (waits) */
    215 		(void)fprintf(cshout, "%ld", r1->ru_nvcsw - r0->ru_nvcsw);
    216 		break;
    217 	    }
    218     (void)fputc('\n', cshout);
    219 }
    220 
    221 static void
    222 pdeltat(struct timeval *t1, struct timeval *t0)
    223 {
    224     struct timeval td;
    225 
    226     timersub(t1, t0, &td);
    227     (void)fprintf(cshout, "%ld.%01ld", (long)td.tv_sec,
    228 	(long)(td.tv_usec / 100000));
    229 }
    230 
    231 #define  P2DIG(i) (void)fprintf(cshout, "%d%d", (i) / 10, (i) % 10)
    232 
    233 void
    234 psecs(long l)
    235 {
    236     int i;
    237 
    238     i = l / 3600;
    239     if (i) {
    240 	(void)fprintf(cshout, "%d:", i);
    241 	i = l % 3600;
    242 	P2DIG(i / 60);
    243 	goto minsec;
    244     }
    245     i = l;
    246     (void)fprintf(cshout, "%d", i / 60);
    247 minsec:
    248     i %= 60;
    249     (void)fputc(':', cshout);
    250     P2DIG(i);
    251 }
    252 
    253 void
    254 pcsecs(long l)			/* PWP: print mm:ss.dd, l is in sec*100 */
    255 {
    256     int i;
    257 
    258     i = l / 360000;
    259     if (i) {
    260 	(void)fprintf(cshout, "%d:", i);
    261 	i = (l % 360000) / 100;
    262 	P2DIG(i / 60);
    263 	goto minsec;
    264     }
    265     i = l / 100;
    266     (void)fprintf(cshout, "%d", i / 60);
    267 minsec:
    268     i %= 60;
    269     (void)fputc(':', cshout);
    270     P2DIG(i);
    271     (void)fputc('.', cshout);
    272     P2DIG((int) (l % 100));
    273 }
    274