1 1.24 simonb /* $NetBSD: time.c,v 1.24 2020/04/23 07:54:53 simonb Exp $ */ 2 1.5 jtc 3 1.1 cgd /* 4 1.5 jtc * Copyright (c) 1987, 1988, 1993 5 1.5 jtc * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.13 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.9 lukem #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.19 lukem __COPYRIGHT("@(#) Copyright (c) 1987, 1988, 1993\ 35 1.19 lukem The Regents of the University of California. All rights reserved."); 36 1.1 cgd #endif /* not lint */ 37 1.1 cgd 38 1.1 cgd #ifndef lint 39 1.5 jtc #if 0 40 1.5 jtc static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 6/6/93"; 41 1.5 jtc #endif 42 1.24 simonb __RCSID("$NetBSD: time.c,v 1.24 2020/04/23 07:54:53 simonb Exp $"); 43 1.1 cgd #endif /* not lint */ 44 1.1 cgd 45 1.1 cgd #include <sys/types.h> 46 1.1 cgd #include <sys/time.h> 47 1.1 cgd #include <sys/resource.h> 48 1.3 jtc #include <sys/wait.h> 49 1.11 kleink #include <errno.h> 50 1.12 christos #include <err.h> 51 1.11 kleink #include <locale.h> 52 1.7 jtc #include <signal.h> 53 1.1 cgd #include <stdio.h> 54 1.4 jtc #include <stdlib.h> 55 1.4 jtc #include <unistd.h> 56 1.1 cgd 57 1.17 matt #include "ext.h" 58 1.17 matt 59 1.20 christos __dead static void usage(void); 60 1.12 christos static void prl(long, const char *); 61 1.22 christos static void prts(const char *, const char *, const struct timespec *, 62 1.22 christos const char *); 63 1.12 christos static void prtv(const char *, const char *, const struct timeval *, 64 1.12 christos const char *); 65 1.9 lukem 66 1.4 jtc int 67 1.16 christos main(int argc, char ** volatile argv) 68 1.1 cgd { 69 1.9 lukem int pid; 70 1.24 simonb int ch, status, prec; 71 1.16 christos int volatile portableflag; 72 1.16 christos int volatile lflag; 73 1.11 kleink const char *decpt; 74 1.23 christos const char *fmt; 75 1.11 kleink const struct lconv *lconv; 76 1.22 christos struct timespec before, after; 77 1.1 cgd struct rusage ru; 78 1.1 cgd 79 1.11 kleink (void)setlocale(LC_ALL, ""); 80 1.11 kleink 81 1.23 christos lflag = portableflag = 0; 82 1.24 simonb prec = 1; 83 1.23 christos fmt = NULL; 84 1.24 simonb while ((ch = getopt(argc, argv, "cf:lpt")) != -1) { 85 1.11 kleink switch (ch) { 86 1.23 christos case 'f': 87 1.23 christos fmt = optarg; 88 1.23 christos portableflag = 0; 89 1.23 christos lflag = 0; 90 1.23 christos break; 91 1.24 simonb case 'c': /* csh format */ 92 1.23 christos fmt = "%Uu %Ss %E %P %X+%Dk %I+%Oio %Fpf+%Ww"; 93 1.18 matt portableflag = 0; 94 1.18 matt lflag = 0; 95 1.17 matt break; 96 1.24 simonb case 'p': /* POSIX.2 format */ 97 1.3 jtc portableflag = 1; 98 1.23 christos fmt = NULL; 99 1.18 matt lflag = 0; 100 1.3 jtc break; 101 1.1 cgd case 'l': 102 1.1 cgd lflag = 1; 103 1.18 matt portableflag = 0; 104 1.23 christos fmt = NULL; 105 1.1 cgd break; 106 1.24 simonb case 't': /* tcsh format */ 107 1.24 simonb fmt = "%Uu %Ss %E %P\t%X+%Dk %I+%Oio %Fpf+%Ww"; 108 1.24 simonb prec = 3; 109 1.24 simonb portableflag = 0; 110 1.24 simonb lflag = 0; 111 1.24 simonb break; 112 1.1 cgd case '?': 113 1.1 cgd default: 114 1.11 kleink usage(); 115 1.1 cgd } 116 1.11 kleink } 117 1.11 kleink argc -= optind; 118 1.11 kleink argv += optind; 119 1.1 cgd 120 1.11 kleink if (argc < 1) 121 1.11 kleink usage(); 122 1.1 cgd 123 1.22 christos (void)clock_gettime(CLOCK_MONOTONIC, &before); 124 1.1 cgd switch(pid = vfork()) { 125 1.1 cgd case -1: /* error */ 126 1.12 christos err(EXIT_FAILURE, "Vfork failed"); 127 1.1 cgd /* NOTREACHED */ 128 1.1 cgd case 0: /* child */ 129 1.11 kleink /* LINTED will return only on failure */ 130 1.1 cgd execvp(*argv, argv); 131 1.12 christos err((errno == ENOENT) ? 127 : 126, "Can't exec `%s'", *argv); 132 1.1 cgd /* NOTREACHED */ 133 1.1 cgd } 134 1.3 jtc 135 1.1 cgd /* parent */ 136 1.1 cgd (void)signal(SIGINT, SIG_IGN); 137 1.1 cgd (void)signal(SIGQUIT, SIG_IGN); 138 1.12 christos if ((pid = wait4(pid, &status, 0, &ru)) == -1) 139 1.12 christos err(EXIT_FAILURE, "wait4 %d failed", pid); 140 1.22 christos (void)clock_gettime(CLOCK_MONOTONIC, &after); 141 1.3 jtc if (!WIFEXITED(status)) 142 1.12 christos warnx("Command terminated abnormally."); 143 1.22 christos timespecsub(&after, &before, &after); 144 1.3 jtc 145 1.11 kleink if ((lconv = localeconv()) == NULL || 146 1.11 kleink (decpt = lconv->decimal_point) == NULL) 147 1.11 kleink decpt = "."; 148 1.11 kleink 149 1.23 christos if (fmt) { 150 1.17 matt static struct rusage null_ru; 151 1.17 matt before.tv_sec = 0; 152 1.22 christos before.tv_nsec = 0; 153 1.24 simonb prusage1(stderr, fmt, prec, &null_ru, &ru, &after, &before); 154 1.17 matt } else if (portableflag) { 155 1.22 christos prts("real ", decpt, &after, "\n"); 156 1.12 christos prtv("user ", decpt, &ru.ru_utime, "\n"); 157 1.12 christos prtv("sys ", decpt, &ru.ru_stime, "\n"); 158 1.3 jtc } else { 159 1.22 christos prts("", decpt, &after, " real "); 160 1.12 christos prtv("", decpt, &ru.ru_utime, " user "); 161 1.12 christos prtv("", decpt, &ru.ru_stime, " sys\n"); 162 1.3 jtc } 163 1.3 jtc 164 1.1 cgd if (lflag) { 165 1.11 kleink int hz = (int)sysconf(_SC_CLK_TCK); 166 1.12 christos unsigned long long ticks; 167 1.12 christos #define SCALE(x) (long)(ticks ? x / ticks : 0) 168 1.1 cgd 169 1.1 cgd ticks = hz * (ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) + 170 1.15 simonb hz * (ru.ru_utime.tv_usec + ru.ru_stime.tv_usec) / 1000000; 171 1.12 christos prl(ru.ru_maxrss, "maximum resident set size"); 172 1.12 christos prl(SCALE(ru.ru_ixrss), "average shared memory size"); 173 1.12 christos prl(SCALE(ru.ru_idrss), "average unshared data size"); 174 1.12 christos prl(SCALE(ru.ru_isrss), "average unshared stack size"); 175 1.12 christos prl(ru.ru_minflt, "page reclaims"); 176 1.12 christos prl(ru.ru_majflt, "page faults"); 177 1.12 christos prl(ru.ru_nswap, "swaps"); 178 1.12 christos prl(ru.ru_inblock, "block input operations"); 179 1.12 christos prl(ru.ru_oublock, "block output operations"); 180 1.12 christos prl(ru.ru_msgsnd, "messages sent"); 181 1.12 christos prl(ru.ru_msgrcv, "messages received"); 182 1.12 christos prl(ru.ru_nsignals, "signals received"); 183 1.12 christos prl(ru.ru_nvcsw, "voluntary context switches"); 184 1.12 christos prl(ru.ru_nivcsw, "involuntary context switches"); 185 1.1 cgd } 186 1.3 jtc 187 1.12 christos return (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE); 188 1.11 kleink } 189 1.11 kleink 190 1.11 kleink static void 191 1.20 christos usage(void) 192 1.11 kleink { 193 1.15 simonb 194 1.24 simonb (void)fprintf(stderr, 195 1.24 simonb "Usage: %s [-clpt] [-f <fmt>] utility [argument ...]\n", 196 1.12 christos getprogname()); 197 1.12 christos exit(EXIT_FAILURE); 198 1.12 christos } 199 1.12 christos 200 1.12 christos static void 201 1.12 christos prl(long val, const char *expn) 202 1.12 christos { 203 1.15 simonb 204 1.15 simonb (void)fprintf(stderr, "%10ld %s\n", val, expn); 205 1.12 christos } 206 1.11 kleink 207 1.12 christos static void 208 1.22 christos prts(const char *pre, const char *decpt, const struct timespec *ts, 209 1.22 christos const char *post) 210 1.22 christos { 211 1.22 christos 212 1.22 christos (void)fprintf(stderr, "%s%9lld%s%02ld%s", pre, (long long)ts->tv_sec, 213 1.22 christos decpt, (long)ts->tv_nsec / 10000000, post); 214 1.22 christos } 215 1.22 christos 216 1.22 christos static void 217 1.12 christos prtv(const char *pre, const char *decpt, const struct timeval *tv, 218 1.12 christos const char *post) 219 1.12 christos { 220 1.15 simonb 221 1.22 christos (void)fprintf(stderr, "%s%9lld%s%02ld%s", pre, (long long)tv->tv_sec, 222 1.22 christos decpt, (long)tv->tv_usec / 10000, post); 223 1.1 cgd } 224