4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
29 #pragma ident "%Z%%M% %I% %E% SMI"
31 #include <sys/types.h>
32 #include <sys/times.h>
34 #include <sys/param.h>
45 #define NSEC_TO_TICK(nsec) ((nsec) / nsec_per_tick)
46 #define NSEC_TO_TICK_ROUNDUP(nsec) NSEC_TO_TICK((nsec) + \
51 static int nsec_per_tick
;
53 void printt(char *, hrtime_t
);
58 main(int argc
, char **argv
)
60 struct tms buffer
, obuffer
;
64 hrtime_t before
, after
, timediff
;
65 char stime
[9], etime
[9];
67 int pflg
= 0, sflg
= 0, oflg
= 0;
70 char ttyid
[12], line
[150];
73 int iline
= 0, i
, nfld
;
75 long chars
= 0, bloks
= 0;
79 hz
= sysconf(_SC_CLK_TCK
);
80 nsec_per_tick
= NANOSEC
/ hz
;
83 while ((c
= getopt(argc
, argv
, "sopfhkmrt")) != EOF
)
85 case 's': sflg
++; break;
86 case 'o': oflg
++; break;
87 case 'p': pflg
++; break;
89 case 'f': strcat(aopt
, "-f "); break;
90 case 'h': strcat(aopt
, "-h "); break;
91 case 'k': strcat(aopt
, "-k "); break;
92 case 'm': strcat(aopt
, "-m "); break;
93 case 'r': strcat(aopt
, "-r "); break;
94 case 't': strcat(aopt
, "-t "); break;
100 fprintf(stderr
, "timex: Missing command\n");
105 * Check to see if accounting is installed and print a somewhat
106 * meaninful message if not.
108 if (((oflg
+pflg
) != 0) && (access("/usr/bin/acctcom", 01) == -1)) {
112 "Information from -p and -o options not available\n");
114 " because process accounting is not operational.\n");
118 sprintf(fname
, "/tmp/tmx%ld", getpid());
119 sprintf(cmd
, "/usr/lib/sa/sadc 1 1 %s", fname
);
122 if (pflg
+ oflg
) hmstime(stime
);
123 before
= gethrtime();
124 (void) times(&obuffer
);
125 if ((p
= fork()) == (pid_t
)-1) {
126 perror("Fork Failed");
127 (void) unlink(fname
);
132 execvp(*(argv
+optind
), (argv
+optind
));
133 fprintf(stderr
, "%s: %s\n", *(argv
+optind
), strerror(errno
));
136 signal(SIGINT
, SIG_IGN
);
137 signal(SIGQUIT
, SIG_IGN
);
138 while (wait(&status
) != p
)
140 if ((status
&0377) != 0)
141 fprintf(stderr
, "Command terminated abnormally.\n");
142 signal(SIGINT
, SIG_DFL
);
143 signal(SIGQUIT
, SIG_DFL
);
144 (void) times(&buffer
);
146 timediff
= after
- before
;
147 if (pflg
+ oflg
) hmstime(etime
);
148 if (sflg
) system(cmd
);
150 fprintf(stderr
, "\n");
151 printt("real", NSEC_TO_TICK_ROUNDUP(timediff
));
152 printt("user", buffer
.tms_cutime
- obuffer
.tms_cutime
);
153 printt("sys ", buffer
.tms_cstime
- obuffer
.tms_cstime
);
154 fprintf(stderr
, "\n");
158 sprintf(ttyid
, "-l %s", ttyname(0)+5);
159 sprintf(cmd
, "acctcom -S %s -E %s -u %s %s -i %s",
160 stime
, etime
, getpwuid(getuid())->pw_name
, ttyid
, aopt
);
161 pipin
= popen(cmd
, "r");
162 while (fscanf(pipin
, "%[^\n]%1c", line
, &eol
) > 1) {
164 fprintf(stderr
, "%s\n", line
);
167 "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
168 fld
[0], fld
[1], fld
[2], fld
[3], fld
[4],
169 fld
[5], fld
[6], fld
[7], fld
[8], fld
[9],
170 fld
[10], fld
[11], fld
[12], fld
[13], fld
[14],
171 fld
[15], fld
[16], fld
[17], fld
[18],
174 for (i
= 0; i
< nfld
; i
++) {
175 if (strcmp(fld
[i
], "CHARS")
178 if (strcmp(fld
[i
], "BLOCKS")
183 chars
+= atol(fld
[ichar
]);
184 bloks
+= atol(fld
[iblok
]);
193 "\nCHARS TRNSFD = %ld\n"
194 "BLOCKS READ = %ld\n", chars
, bloks
);
197 "\nNo process records found!\n");
201 sprintf(cmd
, "/usr/bin/sar -ubdycwaqvmpgrk -f %s 1>&2", fname
);
205 exit(WEXITSTATUS(status
));
209 printt(char *label
, hrtime_t ticks
)
211 long tk
; /* number of leftover ticks */
212 long ss
; /* number of seconds */
213 long mm
; /* number of minutes */
214 long hh
; /* number of hours */
215 longlong_t total
= ticks
;
217 tk
= total
% hz
; /* ticks % hz */
219 ss
= total
% 60; /* ticks / hz % 60 */
221 mm
= total
% 60; /* ticks / hz / 60 % 60 */
222 hh
= total
/ 60; /* ticks / hz / 60 / 60 */
224 (void) fprintf(stderr
, "%s ", label
);
226 /* Display either padding or the elapsed hours */
228 (void) fprintf(stderr
, "%6c", ' ');
230 (void) fprintf(stderr
, "%5ld:", hh
);
234 * Display either nothing or the elapsed minutes, zero
235 * padding (if hours > 0) or space padding (if not).
237 if (mm
== 0L && hh
== 0L) {
238 (void) fprintf(stderr
, "%3c", ' ');
239 } else if (mm
!= 0L && hh
== 0L) {
240 (void) fprintf(stderr
, "%2ld:", mm
);
242 (void) fprintf(stderr
, "%02ld:", mm
);
246 * Display the elapsed seconds; seconds are always
249 if (hh
== 0L && mm
== 0L) {
250 (void) fprintf(stderr
, "%2ld.", ss
);
252 (void) fprintf(stderr
, "%02ld.", ss
);
255 /* Display hundredths of a second. */
256 (void) fprintf(stderr
, "%02ld\n", tk
* 100/hz
);
260 * hmstime() sets current time in hh:mm:ss string format in stime;
264 hmstime(char stime
[])
269 tme
= time((time_t *)0);
271 strncpy(stime
, ltime
+11, 8);
278 fprintf(stderr
, "Usage: timex [-o] [-p [-fhkmrt]] [-s] command\n");