aboutsummaryrefslogtreecommitdiff
path: root/miscutils/time.c
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2008-03-17 09:29:43 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2008-03-17 09:29:43 +0000
commitb44c790e41e281965955a83408f35ea53ecdb3d2 (patch)
tree98514dba64f7b74b9d60882bfeca1e2c4976b033 /miscutils/time.c
parentd25c33f186c7cf3618c34ce79af94fe156f9ab02 (diff)
downloadbusybox-w32-b44c790e41e281965955a83408f35ea53ecdb3d2.tar.gz
busybox-w32-b44c790e41e281965955a83408f35ea53ecdb3d2.tar.bz2
busybox-w32-b44c790e41e281965955a83408f35ea53ecdb3d2.zip
*: fix various kinds of damage to letter 'c' in Arkadiusz Mickiewicz' surname.
chrt,taskset,dc,eject: shrink crontab: call "vi" with just name, no path watchdog: intercept all fatal signals function old new delta xstrtoull_range - 35 +35 static.sg_commands - 18 +18 packed_usage 23698 23712 +14 watchdog_main 148 151 +3 crontab_main 637 638 +1 base 1 - -1 static.ps 4 - -4 pointer 4 - -4 stack_machine 99 92 -7 run_command 273 260 -13 eject_main 360 343 -17 static.C 30 12 -18 ptok 61 38 -23 xstrtol_range 27 - -27 get_token 35 - -35 taskset_main 586 550 -36 chrt_main 411 372 -39 dc_main 158 117 -41 time_main 1127 1037 -90 ------------------------------------------------------------------------------ (add/remove: 2/5 grow/shrink: 3/9 up/down: 71/-355) Total: -284 bytes text data bss dec hex filename 793680 662 7420 801762 c3be2 busybox_old 793327 662 7412 801401 c3a79 busybox_unstripped
Diffstat (limited to 'miscutils/time.c')
-rw-r--r--miscutils/time.c118
1 files changed, 47 insertions, 71 deletions
diff --git a/miscutils/time.c b/miscutils/time.c
index 677ca6d8b..ed4385948 100644
--- a/miscutils/time.c
+++ b/miscutils/time.c
@@ -1,5 +1,5 @@
1/* vi: set sw=4 ts=4: */ 1/* vi: set sw=4 ts=4: */
2/* `time' utility to display resource usage of processes. 2/* 'time' utility to display resource usage of processes.
3 Copyright (C) 1990, 91, 92, 93, 96 Free Software Foundation, Inc. 3 Copyright (C) 1990, 91, 92, 93, 96 Free Software Foundation, Inc.
4 4
5 Licensed under GPL version 2, see file LICENSE in this tarball for details. 5 Licensed under GPL version 2, see file LICENSE in this tarball for details.
@@ -28,7 +28,6 @@ static const char default_format[] ALIGN1 = "real\t%E\nuser\t%u\nsys\t%T";
28/* The output format for the -p option .*/ 28/* The output format for the -p option .*/
29static const char posix_format[] ALIGN1 = "real %e\nuser %U\nsys %S"; 29static const char posix_format[] ALIGN1 = "real %e\nuser %U\nsys %S";
30 30
31
32/* Format string for printing all statistics verbosely. 31/* Format string for printing all statistics verbosely.
33 Keep this output to 24 lines so users on terminals can see it all.*/ 32 Keep this output to 24 lines so users on terminals can see it all.*/
34static const char long_format[] ALIGN1 = 33static const char long_format[] ALIGN1 =
@@ -56,35 +55,31 @@ static const char long_format[] ALIGN1 =
56 "\tPage size (bytes): %Z\n" 55 "\tPage size (bytes): %Z\n"
57 "\tExit status: %x"; 56 "\tExit status: %x";
58 57
59
60/* Wait for and fill in data on child process PID. 58/* Wait for and fill in data on child process PID.
61 Return 0 on error, 1 if ok. */ 59 Return 0 on error, 1 if ok. */
62
63/* pid_t is short on BSDI, so don't try to promote it. */ 60/* pid_t is short on BSDI, so don't try to promote it. */
64static int resuse_end(pid_t pid, resource_t *resp) 61static void resuse_end(pid_t pid, resource_t *resp)
65{ 62{
66 int status;
67 pid_t caught; 63 pid_t caught;
68 64
69 /* Ignore signals, but don't ignore the children. When wait3 65 /* Ignore signals, but don't ignore the children. When wait3
70 returns the child process, set the time the command finished. */ 66 returns the child process, set the time the command finished. */
71 while ((caught = wait3(&status, 0, &resp->ru)) != pid) { 67 while ((caught = wait3(&resp->waitstatus, 0, &resp->ru)) != pid) {
72 if (caught == -1 && errno != EINTR) 68 if (caught == -1 && errno != EINTR) {
73 return 0; 69 bb_perror_msg("wait");
70 return;
71 }
74 } 72 }
75 resp->elapsed_ms = (monotonic_us() / 1000) - resp->elapsed_ms; 73 resp->elapsed_ms = (monotonic_us() / 1000) - resp->elapsed_ms;
76 resp->waitstatus = status;
77 return 1;
78} 74}
79 75
80/* Print ARGV, with each entry in ARGV separated by FILLER. */ 76static void printargv(char *const *argv)
81static void printargv(char *const *argv, const char *filler)
82{ 77{
83 fputs(*argv, stdout); 78 const char *fmt = " %s" + 1;
84 while (*++argv) { 79 do {
85 fputs(filler, stdout); 80 printf(fmt, *argv);
86 fputs(*argv, stdout); 81 fmt = " %s";
87 } 82 } while (*++argv);
88} 83}
89 84
90/* Return the number of kilobytes corresponding to a number of pages PAGES. 85/* Return the number of kilobytes corresponding to a number of pages PAGES.
@@ -94,24 +89,18 @@ static void printargv(char *const *argv, const char *filler)
94 This is funky since the pagesize could be less than 1K. 89 This is funky since the pagesize could be less than 1K.
95 Note: Some machines express getrusage statistics in terms of K, 90 Note: Some machines express getrusage statistics in terms of K,
96 others in terms of pages. */ 91 others in terms of pages. */
97 92static unsigned long ptok(unsigned pagesize, unsigned long pages)
98static unsigned long ptok(unsigned long pages)
99{ 93{
100 static unsigned long ps;
101 unsigned long tmp; 94 unsigned long tmp;
102 95
103 /* Initialization. */
104 if (ps == 0)
105 ps = getpagesize();
106
107 /* Conversion. */ 96 /* Conversion. */
108 if (pages > (LONG_MAX / ps)) { /* Could overflow. */ 97 if (pages > (LONG_MAX / pagesize)) { /* Could overflow. */
109 tmp = pages / 1024; /* Smaller first, */ 98 tmp = pages / 1024; /* Smaller first, */
110 return tmp * ps; /* then larger. */ 99 return tmp * pagesize; /* then larger. */
111 } 100 }
112 /* Could underflow. */ 101 /* Could underflow. */
113 tmp = pages * ps; /* Larger first, */ 102 tmp = pages * pagesize; /* Larger first, */
114 return tmp / 1024; /* then smaller. */ 103 return tmp / 1024; /* then smaller. */
115} 104}
116 105
117/* summarize: Report on the system use of a command. 106/* summarize: Report on the system use of a command.
@@ -162,15 +151,18 @@ static unsigned long ptok(unsigned long pages)
162#define TICKS_PER_SEC 100 151#define TICKS_PER_SEC 100
163#endif 152#endif
164 153
165static void summarize(const char *fmt, char **command, resource_t * resp) 154static void summarize(const char *fmt, char **command, resource_t *resp)
166{ 155{
167 unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */ 156 unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */
168 unsigned cpu_ticks; /* Same, in "CPU ticks" */ 157 unsigned cpu_ticks; /* Same, in "CPU ticks" */
158 unsigned pagesize = getpagesize();
169 159
160 /* Impossible: we do not use WUNTRACED flag in wait()...
170 if (WIFSTOPPED(resp->waitstatus)) 161 if (WIFSTOPPED(resp->waitstatus))
171 printf("Command stopped by signal %u\n", 162 printf("Command stopped by signal %u\n",
172 WSTOPSIG(resp->waitstatus)); 163 WSTOPSIG(resp->waitstatus));
173 else if (WIFSIGNALED(resp->waitstatus)) 164 else */
165 if (WIFSIGNALED(resp->waitstatus))
174 printf("Command terminated by signal %u\n", 166 printf("Command terminated by signal %u\n",
175 WTERMSIG(resp->waitstatus)); 167 WTERMSIG(resp->waitstatus));
176 else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus)) 168 else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus))
@@ -181,7 +173,7 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
181 + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000; 173 + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000;
182 174
183#if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000 175#if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000
184 /* 1000 is exactly divisible by TICKS_PER_SEC */ 176 /* 1000 is exactly divisible by TICKS_PER_SEC (typical) */
185 cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC); 177 cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC);
186#else 178#else
187 cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000; 179 cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000;
@@ -221,12 +213,12 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
221 break; 213 break;
222#endif 214#endif
223 case 'C': /* The command that got timed. */ 215 case 'C': /* The command that got timed. */
224 printargv(command, " "); 216 printargv(command);
225 break; 217 break;
226 case 'D': /* Average unshared data size. */ 218 case 'D': /* Average unshared data size. */
227 printf("%lu", 219 printf("%lu",
228 ptok((UL) resp->ru.ru_idrss) / cpu_ticks + 220 (ptok(pagesize, (UL) resp->ru.ru_idrss) +
229 ptok((UL) resp->ru.ru_isrss) / cpu_ticks); 221 ptok(pagesize, (UL) resp->ru.ru_isrss)) / cpu_ticks);
230 break; 222 break;
231 case 'E': { /* Elapsed real (wall clock) time. */ 223 case 'E': { /* Elapsed real (wall clock) time. */
232 unsigned seconds = resp->elapsed_ms / 1000; 224 unsigned seconds = resp->elapsed_ms / 1000;
@@ -250,12 +242,12 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
250 break; 242 break;
251 case 'K': /* Average mem usage == data+stack+text. */ 243 case 'K': /* Average mem usage == data+stack+text. */
252 printf("%lu", 244 printf("%lu",
253 ptok((UL) resp->ru.ru_idrss) / cpu_ticks + 245 (ptok(pagesize, (UL) resp->ru.ru_idrss) +
254 ptok((UL) resp->ru.ru_isrss) / cpu_ticks + 246 ptok(pagesize, (UL) resp->ru.ru_isrss) +
255 ptok((UL) resp->ru.ru_ixrss) / cpu_ticks); 247 ptok(pagesize, (UL) resp->ru.ru_ixrss)) / cpu_ticks);
256 break; 248 break;
257 case 'M': /* Maximum resident set size. */ 249 case 'M': /* Maximum resident set size. */
258 printf("%lu", ptok((UL) resp->ru.ru_maxrss)); 250 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_maxrss));
259 break; 251 break;
260 case 'O': /* Outputs. */ 252 case 'O': /* Outputs. */
261 printf("%lu", resp->ru.ru_oublock); 253 printf("%lu", resp->ru.ru_oublock);
@@ -308,7 +300,7 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
308 printf("%lu", resp->ru.ru_nswap); 300 printf("%lu", resp->ru.ru_nswap);
309 break; 301 break;
310 case 'X': /* Average shared text size. */ 302 case 'X': /* Average shared text size. */
311 printf("%lu", ptok((UL) resp->ru.ru_ixrss) / cpu_ticks); 303 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_ixrss) / cpu_ticks);
312 break; 304 break;
313 case 'Z': /* Page size. */ 305 case 'Z': /* Page size. */
314 printf("%u", getpagesize()); 306 printf("%u", getpagesize());
@@ -325,7 +317,7 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
325 printf("%lu", resp->ru.ru_nsignals); 317 printf("%lu", resp->ru.ru_nsignals);
326 break; 318 break;
327 case 'p': /* Average stack segment. */ 319 case 'p': /* Average stack segment. */
328 printf("%lu", ptok((UL) resp->ru.ru_isrss) / cpu_ticks); 320 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_isrss) / cpu_ticks);
329 break; 321 break;
330 case 'r': /* Incoming socket messages received. */ 322 case 'r': /* Incoming socket messages received. */
331 printf("%lu", resp->ru.ru_msgrcv); 323 printf("%lu", resp->ru.ru_msgrcv);
@@ -334,7 +326,7 @@ static void summarize(const char *fmt, char **command, resource_t * resp)
334 printf("%lu", resp->ru.ru_msgsnd); 326 printf("%lu", resp->ru.ru_msgsnd);
335 break; 327 break;
336 case 't': /* Average resident set size. */ 328 case 't': /* Average resident set size. */
337 printf("%lu", ptok((UL) resp->ru.ru_idrss) / cpu_ticks); 329 printf("%lu", ptok(pagesize, (UL) resp->ru.ru_idrss) / cpu_ticks);
338 break; 330 break;
339 case 'w': /* Voluntary context switches. */ 331 case 'w': /* Voluntary context switches. */
340 printf("%lu", resp->ru.ru_nvcsw); 332 printf("%lu", resp->ru.ru_nvcsw);
@@ -396,8 +388,7 @@ static void run_command(char *const *cmd, resource_t *resp)
396 interrupt_signal = signal(SIGINT, SIG_IGN); 388 interrupt_signal = signal(SIGINT, SIG_IGN);
397 quit_signal = signal(SIGQUIT, SIG_IGN); 389 quit_signal = signal(SIGQUIT, SIG_IGN);
398 390
399 if (resuse_end(pid, resp) == 0) 391 resuse_end(pid, resp);
400 bb_error_msg("error waiting for child process");
401 392
402 /* Re-enable signals. */ 393 /* Re-enable signals. */
403 signal(SIGINT, interrupt_signal); 394 signal(SIGINT, interrupt_signal);
@@ -405,41 +396,26 @@ static void run_command(char *const *cmd, resource_t *resp)
405} 396}
406 397
407int time_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; 398int time_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
408int time_main(int argc, char **argv) 399int time_main(int argc ATTRIBUTE_UNUSED, char **argv)
409{ 400{
410 resource_t res; 401 resource_t res;
411 const char *output_format = default_format; 402 const char *output_format = default_format;
412 char c; 403 int opt;
413 404
414 goto next; 405 /* "+": stop on first non-option */
415 /* Parse any options -- don't use getopt() here so we don't 406 opt = getopt32(argv, "+vp");
416 * consume the args of our client application... */ 407 argv += optind;
417 while (argc > 0 && argv[0][0] == '-') { 408 if (opt & 1)
418 while ((c = *++*argv)) { 409 output_format = long_format;
419 switch (c) { 410 if (opt & 2)
420 case 'v': 411 output_format = posix_format;
421 output_format = long_format;
422 break;
423 case 'p':
424 output_format = posix_format;
425 break;
426 default:
427 bb_show_usage();
428 }
429 }
430 next:
431 argv++;
432 argc--;
433 if (!argc)
434 bb_show_usage();
435 }
436 412
437 run_command(argv, &res); 413 run_command(argv, &res);
438 414
439 /* Cheat. printf's are shorter :) */ 415 /* Cheat. printf's are shorter :) */
440 /* (but see bb_putchar() body for additional wrinkle!) */ 416 /* (but see bb_putchar() body for additional wrinkle!) */
417 xdup2(2, 1); /* just in case libc does something silly :( */
441 stdout = stderr; 418 stdout = stderr;
442 dup2(2, 1); /* just in case libc does something silly :( */
443 summarize(output_format, argv, &res); 419 summarize(output_format, argv, &res);
444 420
445 if (WIFSTOPPED(res.waitstatus)) 421 if (WIFSTOPPED(res.waitstatus))