1 /* $OpenBSD: time.c,v 1.11 2001/11/22 10:42:39 mpech Exp $ */ 2 /* $NetBSD: time.c,v 1.7 1995/06/27 00:34:00 jtc Exp $ */ 3 4 /* 5 * Copyright (c) 1987, 1988, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 3. All advertising materials mentioning features or use of this software 17 * must display the following acknowledgement: 18 * This product includes software developed by the University of 19 * California, Berkeley and its contributors. 20 * 4. Neither the name of the University nor the names of its contributors 21 * may be used to endorse or promote products derived from this software 22 * without specific prior written permission. 23 * 24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 34 * SUCH DAMAGE. 35 */ 36 37 #ifndef lint 38 static char copyright[] = 39 "@(#) Copyright (c) 1987, 1988, 1993\n\ 40 The Regents of the University of California. All rights reserved.\n"; 41 #endif /* not lint */ 42 43 #ifndef lint 44 #if 0 45 static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 6/6/93"; 46 #endif 47 static char rcsid[] = "$OpenBSD: time.c,v 1.11 2001/11/22 10:42:39 mpech Exp $"; 48 #endif /* not lint */ 49 50 #include <sys/param.h> 51 #include <sys/time.h> 52 #include <sys/resource.h> 53 #include <sys/wait.h> 54 #include <sys/sysctl.h> 55 56 #include <err.h> 57 #include <errno.h> 58 #include <signal.h> 59 #include <stdio.h> 60 #include <stdlib.h> 61 #include <unistd.h> 62 63 int lflag; 64 int portableflag; 65 66 __dead void usage __P((void)); 67 68 int 69 main(argc, argv) 70 int argc; 71 char **argv; 72 { 73 int pid; 74 int ch, status; 75 struct timeval before, after; 76 struct rusage ru; 77 int exitonsig = 0; 78 79 80 while ((ch = getopt(argc, argv, "lp")) != -1) { 81 switch(ch) { 82 case 'l': 83 lflag = 1; 84 break; 85 case 'p': 86 portableflag = 1; 87 break; 88 case '?': 89 default: 90 usage(); 91 /* NOTREACHED */ 92 } 93 } 94 95 argc -= optind; 96 argv += optind; 97 98 if (argc < 1) 99 usage(); 100 101 gettimeofday(&before, (struct timezone *)NULL); 102 switch(pid = vfork()) { 103 case -1: /* error */ 104 perror("time"); 105 exit(1); 106 /* NOTREACHED */ 107 case 0: /* child */ 108 execvp(*argv, argv); 109 perror(*argv); 110 _exit((errno == ENOENT) ? 127 : 126); 111 /* NOTREACHED */ 112 } 113 114 /* parent */ 115 (void)signal(SIGINT, SIG_IGN); 116 (void)signal(SIGQUIT, SIG_IGN); 117 while (wait3(&status, 0, &ru) != pid) 118 ; 119 gettimeofday(&after, (struct timezone *)NULL); 120 if (WIFSIGNALED(status)) 121 exitonsig = WTERMSIG(status); 122 if (!WIFEXITED(status)) 123 fprintf(stderr, "Command terminated abnormally.\n"); 124 timersub(&after, &before, &after); 125 126 if (portableflag) { 127 fprintf(stderr, "real %9ld.%02ld\n", 128 after.tv_sec, after.tv_usec/10000); 129 fprintf(stderr, "user %9ld.%02ld\n", 130 ru.ru_utime.tv_sec, ru.ru_utime.tv_usec/10000); 131 fprintf(stderr, "sys %9ld.%02ld\n", 132 ru.ru_stime.tv_sec, ru.ru_stime.tv_usec/10000); 133 } else { 134 135 fprintf(stderr, "%9ld.%02ld real ", 136 after.tv_sec, after.tv_usec/10000); 137 fprintf(stderr, "%9ld.%02ld user ", 138 ru.ru_utime.tv_sec, ru.ru_utime.tv_usec/10000); 139 fprintf(stderr, "%9ld.%02ld sys\n", 140 ru.ru_stime.tv_sec, ru.ru_stime.tv_usec/10000); 141 } 142 143 if (lflag) { 144 int hz; 145 long ticks; 146 int mib[2]; 147 struct clockinfo clkinfo; 148 size_t size; 149 150 mib[0] = CTL_KERN; 151 mib[1] = KERN_CLOCKRATE; 152 size = sizeof(clkinfo); 153 if (sysctl(mib, 2, &clkinfo, &size, NULL, 0) < 0) 154 err(1, "sysctl"); 155 156 hz = clkinfo.hz; 157 158 ticks = hz * (ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) + 159 hz * (ru.ru_utime.tv_usec + ru.ru_stime.tv_usec) / 1000000; 160 161 fprintf(stderr, "%10ld %s\n", 162 ru.ru_maxrss, "maximum resident set size"); 163 fprintf(stderr, "%10ld %s\n", ticks ? ru.ru_ixrss / ticks : 0, 164 "average shared memory size"); 165 fprintf(stderr, "%10ld %s\n", ticks ? ru.ru_idrss / ticks : 0, 166 "average unshared data size"); 167 fprintf(stderr, "%10ld %s\n", ticks ? ru.ru_isrss / ticks : 0, 168 "average unshared stack size"); 169 fprintf(stderr, "%10ld %s\n", 170 ru.ru_minflt, "minor page faults"); 171 fprintf(stderr, "%10ld %s\n", 172 ru.ru_majflt, "major page faults"); 173 fprintf(stderr, "%10ld %s\n", 174 ru.ru_nswap, "swaps"); 175 fprintf(stderr, "%10ld %s\n", 176 ru.ru_inblock, "block input operations"); 177 fprintf(stderr, "%10ld %s\n", 178 ru.ru_oublock, "block output operations"); 179 fprintf(stderr, "%10ld %s\n", 180 ru.ru_msgsnd, "messages sent"); 181 fprintf(stderr, "%10ld %s\n", 182 ru.ru_msgrcv, "messages received"); 183 fprintf(stderr, "%10ld %s\n", 184 ru.ru_nsignals, "signals received"); 185 fprintf(stderr, "%10ld %s\n", 186 ru.ru_nvcsw, "voluntary context switches"); 187 fprintf(stderr, "%10ld %s\n", 188 ru.ru_nivcsw, "involuntary context switches"); 189 } 190 191 if (exitonsig) { 192 if (signal(exitonsig, SIG_DFL) == SIG_ERR) 193 perror("signal"); 194 else 195 kill(getpid(), exitonsig); 196 } 197 exit(WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE); 198 } 199 200 __dead void 201 usage() 202 { 203 extern char *__progname; 204 205 (void)fprintf(stderr, "usage: %s [-lp] command\n", __progname); 206 exit(1); 207 } 208