1/*	$NetBSD: time.c,v 1.9 1997/10/20 03:28:21 lukem Exp $	*/
2
3/*
4 * Copyright (c) 1987, 1988, 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. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *	This product includes software developed by the University of
18 *	California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36#include <sys/cdefs.h>
37#ifndef lint
38__COPYRIGHT("@(#) Copyright (c) 1987, 1988, 1993\n\
39	The Regents of the University of California.  All rights reserved.\n");
40#endif /* not lint */
41
42#ifndef lint
43#if 0
44static char sccsid[] = "@(#)time.c	8.1 (Berkeley) 6/6/93";
45#endif
46__RCSID("$NetBSD: time.c,v 1.9 1997/10/20 03:28:21 lukem Exp $");
47#endif /* not lint */
48
49#include <sys/types.h>
50#include <sys/time.h>
51#include <sys/resource.h>
52#include <sys/wait.h>
53#include <signal.h>
54#include <stdio.h>
55#include <stdlib.h>
56#include <unistd.h>
57#include <errno.h>
58
59int lflag;
60int portableflag;
61
62int	main __P((int, char **));
63
64int
65main(argc, argv)
66	int argc;
67	char **argv;
68{
69	int pid;
70	int ch, status;
71	struct timeval before, after;
72	struct rusage ru;
73
74#ifdef __GNUC__		/* XXX: borken gcc */
75	(void)&argv;
76#endif
77	lflag = 0;
78	while ((ch = getopt(argc, argv, "lp")) != -1)
79		switch((char)ch) {
80		case 'p':
81			portableflag = 1;
82			break;
83		case 'l':
84			lflag = 1;
85			break;
86		case '?':
87		default:
88			fprintf(stderr, "usage: time [-lp] command.\n");
89			exit(1);
90		}
91
92	if (!(argc -= optind))
93		exit(0);
94	argv += optind;
95
96	gettimeofday(&before, (struct timezone *)NULL);
97	switch(pid = vfork()) {
98	case -1:			/* error */
99		perror("time");
100		exit(1);
101		/* NOTREACHED */
102	case 0:				/* child */
103		execvp(*argv, argv);
104		perror(*argv);
105		_exit((errno == ENOENT) ? 127 : 126);
106		/* NOTREACHED */
107	}
108
109	/* parent */
110	(void)signal(SIGINT, SIG_IGN);
111	(void)signal(SIGQUIT, SIG_IGN);
112	while (wait3(&status, 0, &ru) != pid);
113	gettimeofday(&after, (struct timezone *)NULL);
114	if (!WIFEXITED(status))
115		fprintf(stderr, "Command terminated abnormally.\n");
116	timersub(&after, &before, &after);
117
118	if (portableflag) {
119		fprintf (stderr, "real %9ld.%02ld\n",
120			(long)after.tv_sec, (long)after.tv_usec/10000);
121		fprintf (stderr, "user %9ld.%02ld\n",
122			(long)ru.ru_utime.tv_sec, (long)ru.ru_utime.tv_usec/10000);
123		fprintf (stderr, "sys  %9ld.%02ld\n",
124			(long)ru.ru_stime.tv_sec, (long)ru.ru_stime.tv_usec/10000);
125	} else {
126
127		fprintf(stderr, "%9ld.%02ld real ",
128			(long)after.tv_sec, (long)after.tv_usec/10000);
129		fprintf(stderr, "%9ld.%02ld user ",
130			(long)ru.ru_utime.tv_sec, (long)ru.ru_utime.tv_usec/10000);
131		fprintf(stderr, "%9ld.%02ld sys\n",
132			(long)ru.ru_stime.tv_sec, (long)ru.ru_stime.tv_usec/10000);
133	}
134
135	if (lflag) {
136		int hz = 100;			/* XXX */
137		long ticks;
138
139		ticks = hz * (ru.ru_utime.tv_sec + ru.ru_stime.tv_sec) +
140		     hz * (ru.ru_utime.tv_usec + ru.ru_stime.tv_usec) / 1000000;
141
142		fprintf(stderr, "%10ld  %s\n",
143			ru.ru_maxrss, "maximum resident set size");
144		fprintf(stderr, "%10ld  %s\n", ticks ? ru.ru_ixrss / ticks : 0,
145			"average shared memory size");
146		fprintf(stderr, "%10ld  %s\n", ticks ? ru.ru_idrss / ticks : 0,
147			"average unshared data size");
148		fprintf(stderr, "%10ld  %s\n", ticks ? ru.ru_isrss / ticks : 0,
149			"average unshared stack size");
150		fprintf(stderr, "%10ld  %s\n",
151			ru.ru_minflt, "page reclaims");
152		fprintf(stderr, "%10ld  %s\n",
153			ru.ru_majflt, "page faults");
154		fprintf(stderr, "%10ld  %s\n",
155			ru.ru_nswap, "swaps");
156		fprintf(stderr, "%10ld  %s\n",
157			ru.ru_inblock, "block input operations");
158		fprintf(stderr, "%10ld  %s\n",
159			ru.ru_oublock, "block output operations");
160		fprintf(stderr, "%10ld  %s\n",
161			ru.ru_msgsnd, "messages sent");
162		fprintf(stderr, "%10ld  %s\n",
163			ru.ru_msgrcv, "messages received");
164		fprintf(stderr, "%10ld  %s\n",
165			ru.ru_nsignals, "signals received");
166		fprintf(stderr, "%10ld  %s\n",
167			ru.ru_nvcsw, "voluntary context switches");
168		fprintf(stderr, "%10ld  %s\n",
169			ru.ru_nivcsw, "involuntary context switches");
170	}
171
172	exit (WIFEXITED(status) ? WEXITSTATUS(status) : EXIT_FAILURE);
173}
174