aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2006-12-22 13:43:19 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2006-12-22 13:43:19 +0000
commitc5cb38f4d9fa90fdd01ea258390d0059138616b5 (patch)
treedad37097bc7e7489664f3bc814235aee5f88a146
parentf93ab47c4560b2a1a3130ac17d0bfb886f09ece8 (diff)
downloadbusybox-w32-c5cb38f4d9fa90fdd01ea258390d0059138616b5.tar.gz
busybox-w32-c5cb38f4d9fa90fdd01ea258390d0059138616b5.tar.bz2
busybox-w32-c5cb38f4d9fa90fdd01ea258390d0059138616b5.zip
time: -200 bytes of text
-rw-r--r--miscutils/time.c180
1 files changed, 96 insertions, 84 deletions
diff --git a/miscutils/time.c b/miscutils/time.c
index 7682a2679..df10eeb02 100644
--- a/miscutils/time.c
+++ b/miscutils/time.c
@@ -100,18 +100,14 @@ static int resuse_end(pid_t pid, resource_t * resp)
100 return 1; 100 return 1;
101} 101}
102 102
103/* Print ARGV to FP, with each entry in ARGV separated by FILLER. */ 103/* Print ARGV, with each entry in ARGV separated by FILLER. */
104static void fprintargv(FILE * fp, char *const *argv, const char *filler) 104static void printargv(char *const *argv, const char *filler)
105{ 105{
106 char *const *av; 106 fputs(*argv, stdout);
107 107 while (*++argv) {
108 av = argv; 108 fputs(filler, stdout);
109 fputs(*av, fp); 109 fputs(*argv, stdout);
110 while (*++av) {
111 fputs(filler, fp);
112 fputs(*av, fp);
113 } 110 }
114 die_if_ferror(fp, "output");
115} 111}
116 112
117/* Return the number of kilobytes corresponding to a number of pages PAGES. 113/* Return the number of kilobytes corresponding to a number of pages PAGES.
@@ -124,28 +120,26 @@ static void fprintargv(FILE * fp, char *const *argv, const char *filler)
124 120
125static unsigned long ptok(unsigned long pages) 121static unsigned long ptok(unsigned long pages)
126{ 122{
127 static unsigned long ps = 0; 123 static unsigned long ps;
128 unsigned long tmp; 124 unsigned long tmp;
129 static long size = LONG_MAX;
130 125
131 /* Initialization. */ 126 /* Initialization. */
132 if (ps == 0) 127 if (ps == 0)
133 ps = (long) getpagesize(); 128 ps = getpagesize();
134 129
135 /* Conversion. */ 130 /* Conversion. */
136 if (pages > (LONG_MAX / ps)) { /* Could overflow. */ 131 if (pages > (LONG_MAX / ps)) { /* Could overflow. */
137 tmp = pages / 1024; /* Smaller first, */ 132 tmp = pages / 1024; /* Smaller first, */
138 size = tmp * ps; /* then larger. */ 133 return tmp * ps; /* then larger. */
139 } else { /* Could underflow. */
140 tmp = pages * ps; /* Larger first, */
141 size = tmp / 1024; /* then smaller. */
142 } 134 }
143 return size; 135 /* Could underflow. */
136 tmp = pages * ps; /* Larger first, */
137 return tmp / 1024; /* then smaller. */
144} 138}
145 139
146/* summarize: Report on the system use of a command. 140/* summarize: Report on the system use of a command.
147 141
148 Copy the FMT argument to FP except that `%' sequences 142 Print the FMT argument except that `%' sequences
149 have special meaning, and `\n' and `\t' are translated into 143 have special meaning, and `\n' and `\t' are translated into
150 newline and tab, respectively, and `\\' is translated into `\'. 144 newline and tab, respectively, and `\\' is translated into `\'.
151 145
@@ -183,25 +177,23 @@ static unsigned long ptok(unsigned long pages)
183 to kbytes by multiplying by the page size, dividing by 1024, 177 to kbytes by multiplying by the page size, dividing by 1024,
184 and dividing by elapsed real time. 178 and dividing by elapsed real time.
185 179
186 FP is the stream to print to.
187 FMT is the format string, interpreted as described above. 180 FMT is the format string, interpreted as described above.
188 COMMAND is the command and args that are being summarized. 181 COMMAND is the command and args that are being summarized.
189 RESP is resource information on the command. */ 182 RESP is resource information on the command. */
190 183
191static void summarize(FILE * fp, const char *fmt, char **command, 184static void summarize(const char *fmt, char **command, resource_t * resp)
192 resource_t * resp)
193{ 185{
194 unsigned long r; /* Elapsed real milliseconds. */ 186 unsigned long r; /* Elapsed real milliseconds. */
195 unsigned long v; /* Elapsed virtual (CPU) milliseconds. */ 187 unsigned long v; /* Elapsed virtual (CPU) milliseconds. */
196 188
197 if (WIFSTOPPED(resp->waitstatus)) 189 if (WIFSTOPPED(resp->waitstatus))
198 fprintf(fp, "Command stopped by signal %d\n", 190 printf("Command stopped by signal %d\n",
199 WSTOPSIG(resp->waitstatus)); 191 WSTOPSIG(resp->waitstatus));
200 else if (WIFSIGNALED(resp->waitstatus)) 192 else if (WIFSIGNALED(resp->waitstatus))
201 fprintf(fp, "Command terminated by signal %d\n", 193 printf("Command terminated by signal %d\n",
202 WTERMSIG(resp->waitstatus)); 194 WTERMSIG(resp->waitstatus));
203 else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus)) 195 else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus))
204 fprintf(fp, "Command exited with non-zero status %d\n", 196 printf("Command exited with non-zero status %d\n",
205 WEXITSTATUS(resp->waitstatus)); 197 WEXITSTATUS(resp->waitstatus));
206 198
207 /* Convert all times to milliseconds. Occasionally, one of these values 199 /* Convert all times to milliseconds. Occasionally, one of these values
@@ -214,178 +206,194 @@ static void summarize(FILE * fp, const char *fmt, char **command,
214 v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC + 206 v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC +
215 resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC; 207 resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC;
216 208
209 /* putchar() != putc(stdout) in glibc! */
210
217 while (*fmt) { 211 while (*fmt) {
212 /* Handle leading literal part */
213 int n = strcspn(fmt, "%\\");
214 if (n) {
215 printf("%.*s", n, fmt);
216 fmt += n;
217 continue;
218 }
219
218 switch (*fmt) { 220 switch (*fmt) {
221#ifdef NOT_NEEDED
222 /* Handle literal char */
223 /* Usually we optimize for size, but there is a limit
224 * for everything. With this we do a lot of 1-byte writes */
225 default:
226 putc(*fmt, stdout);
227 break;
228#endif
229
219 case '%': 230 case '%':
220 switch (*++fmt) { 231 switch (*++fmt) {
221 case '%': /* Literal '%'. */ 232#ifdef NOT_NEEDED_YET
222 putc('%', fp); 233 /* Our format strings do not have these */
234 /* and we do not take format str from user */
235 default:
236 putc('%', stdout);
237 /*FALLTHROUGH*/
238 case '%':
239 if (!*fmt) goto ret;
240 putc(*fmt, stdout);
223 break; 241 break;
242#endif
224 case 'C': /* The command that got timed. */ 243 case 'C': /* The command that got timed. */
225 fprintargv(fp, command, " "); 244 printargv(command, " ");
226 break; 245 break;
227 case 'D': /* Average unshared data size. */ 246 case 'D': /* Average unshared data size. */
228 fprintf(fp, "%lu", 247 printf("%lu",
229 MSEC_TO_TICKS(v) == 0 ? 0 : 248 MSEC_TO_TICKS(v) == 0 ? 0 :
230 ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) + 249 ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
231 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v)); 250 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
232 break; 251 break;
233 case 'E': /* Elapsed real (wall clock) time. */ 252 case 'E': /* Elapsed real (wall clock) time. */
234 if (resp->elapsed.tv_sec >= 3600) /* One hour -> h:m:s. */ 253 if (resp->elapsed.tv_sec >= 3600) /* One hour -> h:m:s. */
235 fprintf(fp, "%ldh %ldm %02lds", 254 printf("%ldh %ldm %02lds",
236 resp->elapsed.tv_sec / 3600, 255 resp->elapsed.tv_sec / 3600,
237 (resp->elapsed.tv_sec % 3600) / 60, 256 (resp->elapsed.tv_sec % 3600) / 60,
238 resp->elapsed.tv_sec % 60); 257 resp->elapsed.tv_sec % 60);
239 else 258 else
240 fprintf(fp, "%ldm %ld.%02lds", /* -> m:s. */ 259 printf("%ldm %ld.%02lds", /* -> m:s. */
241 resp->elapsed.tv_sec / 60, 260 resp->elapsed.tv_sec / 60,
242 resp->elapsed.tv_sec % 60, 261 resp->elapsed.tv_sec % 60,
243 resp->elapsed.tv_usec / 10000); 262 resp->elapsed.tv_usec / 10000);
244 break; 263 break;
245 case 'F': /* Major page faults. */ 264 case 'F': /* Major page faults. */
246 fprintf(fp, "%ld", resp->ru.ru_majflt); 265 printf("%ld", resp->ru.ru_majflt);
247 break; 266 break;
248 case 'I': /* Inputs. */ 267 case 'I': /* Inputs. */
249 fprintf(fp, "%ld", resp->ru.ru_inblock); 268 printf("%ld", resp->ru.ru_inblock);
250 break; 269 break;
251 case 'K': /* Average mem usage == data+stack+text. */ 270 case 'K': /* Average mem usage == data+stack+text. */
252 fprintf(fp, "%lu", 271 printf("%lu",
253 MSEC_TO_TICKS(v) == 0 ? 0 : 272 MSEC_TO_TICKS(v) == 0 ? 0 :
254 ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) + 273 ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
255 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v) + 274 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v) +
256 ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v)); 275 ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
257 break; 276 break;
258 case 'M': /* Maximum resident set size. */ 277 case 'M': /* Maximum resident set size. */
259 fprintf(fp, "%lu", ptok((UL) resp->ru.ru_maxrss)); 278 printf("%lu", ptok((UL) resp->ru.ru_maxrss));
260 break; 279 break;
261 case 'O': /* Outputs. */ 280 case 'O': /* Outputs. */
262 fprintf(fp, "%ld", resp->ru.ru_oublock); 281 printf("%ld", resp->ru.ru_oublock);
263 break; 282 break;
264 case 'P': /* Percent of CPU this job got. */ 283 case 'P': /* Percent of CPU this job got. */
265 /* % cpu is (total cpu time)/(elapsed time). */ 284 /* % cpu is (total cpu time)/(elapsed time). */
266 if (r > 0) 285 if (r > 0)
267 fprintf(fp, "%lu%%", (v * 100 / r)); 286 printf("%lu%%", (v * 100 / r));
268 else 287 else
269 fprintf(fp, "?%%"); 288 printf("?%%");
270 break; 289 break;
271 case 'R': /* Minor page faults (reclaims). */ 290 case 'R': /* Minor page faults (reclaims). */
272 fprintf(fp, "%ld", resp->ru.ru_minflt); 291 printf("%ld", resp->ru.ru_minflt);
273 break; 292 break;
274 case 'S': /* System time. */ 293 case 'S': /* System time. */
275 fprintf(fp, "%ld.%02ld", 294 printf("%ld.%02ld",
276 resp->ru.ru_stime.tv_sec, 295 resp->ru.ru_stime.tv_sec,
277 resp->ru.ru_stime.TV_MSEC / 10); 296 resp->ru.ru_stime.TV_MSEC / 10);
278 break; 297 break;
279 case 'T': /* System time. */ 298 case 'T': /* System time. */
280 if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */ 299 if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */
281 fprintf(fp, "%ldh %ldm %02lds", 300 printf("%ldh %ldm %02lds",
282 resp->ru.ru_stime.tv_sec / 3600, 301 resp->ru.ru_stime.tv_sec / 3600,
283 (resp->ru.ru_stime.tv_sec % 3600) / 60, 302 (resp->ru.ru_stime.tv_sec % 3600) / 60,
284 resp->ru.ru_stime.tv_sec % 60); 303 resp->ru.ru_stime.tv_sec % 60);
285 else 304 else
286 fprintf(fp, "%ldm %ld.%02lds", /* -> m:s. */ 305 printf("%ldm %ld.%02lds", /* -> m:s. */
287 resp->ru.ru_stime.tv_sec / 60, 306 resp->ru.ru_stime.tv_sec / 60,
288 resp->ru.ru_stime.tv_sec % 60, 307 resp->ru.ru_stime.tv_sec % 60,
289 resp->ru.ru_stime.tv_usec / 10000); 308 resp->ru.ru_stime.tv_usec / 10000);
290 break; 309 break;
291 case 'U': /* User time. */ 310 case 'U': /* User time. */
292 fprintf(fp, "%ld.%02ld", 311 printf("%ld.%02ld",
293 resp->ru.ru_utime.tv_sec, 312 resp->ru.ru_utime.tv_sec,
294 resp->ru.ru_utime.TV_MSEC / 10); 313 resp->ru.ru_utime.TV_MSEC / 10);
295 break; 314 break;
296 case 'u': /* User time. */ 315 case 'u': /* User time. */
297 if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */ 316 if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */
298 fprintf(fp, "%ldh %ldm %02lds", 317 printf("%ldh %ldm %02lds",
299 resp->ru.ru_utime.tv_sec / 3600, 318 resp->ru.ru_utime.tv_sec / 3600,
300 (resp->ru.ru_utime.tv_sec % 3600) / 60, 319 (resp->ru.ru_utime.tv_sec % 3600) / 60,
301 resp->ru.ru_utime.tv_sec % 60); 320 resp->ru.ru_utime.tv_sec % 60);
302 else 321 else
303 fprintf(fp, "%ldm %ld.%02lds", /* -> m:s. */ 322 printf("%ldm %ld.%02lds", /* -> m:s. */
304 resp->ru.ru_utime.tv_sec / 60, 323 resp->ru.ru_utime.tv_sec / 60,
305 resp->ru.ru_utime.tv_sec % 60, 324 resp->ru.ru_utime.tv_sec % 60,
306 resp->ru.ru_utime.tv_usec / 10000); 325 resp->ru.ru_utime.tv_usec / 10000);
307 break; 326 break;
308 case 'W': /* Times swapped out. */ 327 case 'W': /* Times swapped out. */
309 fprintf(fp, "%ld", resp->ru.ru_nswap); 328 printf("%ld", resp->ru.ru_nswap);
310 break; 329 break;
311 case 'X': /* Average shared text size. */ 330 case 'X': /* Average shared text size. */
312 fprintf(fp, "%lu", 331 printf("%lu",
313 MSEC_TO_TICKS(v) == 0 ? 0 : 332 MSEC_TO_TICKS(v) == 0 ? 0 :
314 ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v)); 333 ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
315 break; 334 break;
316 case 'Z': /* Page size. */ 335 case 'Z': /* Page size. */
317 fprintf(fp, "%d", getpagesize()); 336 printf("%d", getpagesize());
318 break; 337 break;
319 case 'c': /* Involuntary context switches. */ 338 case 'c': /* Involuntary context switches. */
320 fprintf(fp, "%ld", resp->ru.ru_nivcsw); 339 printf("%ld", resp->ru.ru_nivcsw);
321 break; 340 break;
322 case 'e': /* Elapsed real time in seconds. */ 341 case 'e': /* Elapsed real time in seconds. */
323 fprintf(fp, "%ld.%02ld", 342 printf("%ld.%02ld",
324 resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000); 343 resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000);
325 break; 344 break;
326 case 'k': /* Signals delivered. */ 345 case 'k': /* Signals delivered. */
327 fprintf(fp, "%ld", resp->ru.ru_nsignals); 346 printf("%ld", resp->ru.ru_nsignals);
328 break; 347 break;
329 case 'p': /* Average stack segment. */ 348 case 'p': /* Average stack segment. */
330 fprintf(fp, "%lu", 349 printf("%lu",
331 MSEC_TO_TICKS(v) == 0 ? 0 : 350 MSEC_TO_TICKS(v) == 0 ? 0 :
332 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v)); 351 ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
333 break; 352 break;
334 case 'r': /* Incoming socket messages received. */ 353 case 'r': /* Incoming socket messages received. */
335 fprintf(fp, "%ld", resp->ru.ru_msgrcv); 354 printf("%ld", resp->ru.ru_msgrcv);
336 break; 355 break;
337 case 's': /* Outgoing socket messages sent. */ 356 case 's': /* Outgoing socket messages sent. */
338 fprintf(fp, "%ld", resp->ru.ru_msgsnd); 357 printf("%ld", resp->ru.ru_msgsnd);
339 break; 358 break;
340 case 't': /* Average resident set size. */ 359 case 't': /* Average resident set size. */
341 fprintf(fp, "%lu", 360 printf("%lu",
342 MSEC_TO_TICKS(v) == 0 ? 0 : 361 MSEC_TO_TICKS(v) == 0 ? 0 :
343 ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v)); 362 ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v));
344 break; 363 break;
345 case 'w': /* Voluntary context switches. */ 364 case 'w': /* Voluntary context switches. */
346 fprintf(fp, "%ld", resp->ru.ru_nvcsw); 365 printf("%ld", resp->ru.ru_nvcsw);
347 break; 366 break;
348 case 'x': /* Exit status. */ 367 case 'x': /* Exit status. */
349 fprintf(fp, "%d", WEXITSTATUS(resp->waitstatus)); 368 printf("%d", WEXITSTATUS(resp->waitstatus));
350 break; 369 break;
351 case '\0':
352 putc('?', fp);
353 return;
354 default:
355 putc('?', fp);
356 putc(*fmt, fp);
357 } 370 }
358 ++fmt;
359 break; 371 break;
360 372
373#ifdef NOT_NEEDED_YET
361 case '\\': /* Format escape. */ 374 case '\\': /* Format escape. */
362 switch (*++fmt) { 375 switch (*++fmt) {
376 default:
377 putc('\\', stdout);
378 /*FALLTHROUGH*/
379 case '\\':
380 if (!*fmt) goto ret;
381 putc(*fmt, stdout);
382 break;
363 case 't': 383 case 't':
364 putc('\t', fp); 384 putc('\t', stdout);
365 break; 385 break;
366 case 'n': 386 case 'n':
367 putc('\n', fp); 387 putc('\n', stdout);
368 break;
369 case '\\':
370 putc('\\', fp);
371 break; 388 break;
372 default:
373 putc('?', fp);
374 putc('\\', fp);
375 putc(*fmt, fp);
376 } 389 }
377 ++fmt;
378 break; 390 break;
379 391#endif
380 default:
381 putc(*fmt++, fp);
382 } 392 }
383 393 ++fmt;
384 die_if_ferror(fp, "output");
385 } 394 }
386 putc('\n', fp); 395 /* ret: */
387 396 putc('\n', stdout);
388 die_if_ferror(fp, "output");
389} 397}
390 398
391/* Run command CMD and return statistics on it. 399/* Run command CMD and return statistics on it.
@@ -449,7 +457,11 @@ int time_main(int argc, char **argv)
449 } 457 }
450 458
451 run_command(argv, &res); 459 run_command(argv, &res);
452 summarize(stderr, output_format, argv, &res); 460
461 /* Cheat. printf's are shorter :) */
462 stdout = stderr;
463 dup2(2, 1); /* just in case libc does something silly :( */
464 summarize(output_format, argv, &res);
453 465
454 if (WIFSTOPPED(res.waitstatus)) 466 if (WIFSTOPPED(res.waitstatus))
455 return WSTOPSIG(res.waitstatus); 467 return WSTOPSIG(res.waitstatus);
@@ -457,5 +469,5 @@ int time_main(int argc, char **argv)
457 return WTERMSIG(res.waitstatus); 469 return WTERMSIG(res.waitstatus);
458 if (WIFEXITED(res.waitstatus)) 470 if (WIFEXITED(res.waitstatus))
459 return WEXITSTATUS(res.waitstatus); 471 return WEXITSTATUS(res.waitstatus);
460 return 0; 472 fflush_stdout_and_exit(0);
461} 473}