diff options
author | Ron Yorston <rmy@pobox.com> | 2020-04-06 09:03:52 +0100 |
---|---|---|
committer | Ron Yorston <rmy@pobox.com> | 2020-04-06 09:03:52 +0100 |
commit | 9181e1363f09f80ba822175886450b751e408f14 (patch) | |
tree | 000415bab289dd387e9217db9c1da7b0c2bf8549 /miscutils | |
parent | 4ecfc9fc115221ec66769915bf02ac37c40ffcd5 (diff) | |
download | busybox-w32-9181e1363f09f80ba822175886450b751e408f14.tar.gz busybox-w32-9181e1363f09f80ba822175886450b751e408f14.tar.bz2 busybox-w32-9181e1363f09f80ba822175886450b751e408f14.zip |
time: WIN32 port
Port the time applet to WIN32. This requires the implemntation of
a replacement for wait3(2).
Only elapsed, user and system times are supported, not the memory
and i/o statistics reported by GNU time.
Diffstat (limited to 'miscutils')
-rw-r--r-- | miscutils/time.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/miscutils/time.c b/miscutils/time.c index d15d363f3..eace390e6 100644 --- a/miscutils/time.c +++ b/miscutils/time.c | |||
@@ -22,12 +22,21 @@ | |||
22 | //kbuild:lib-$(CONFIG_TIME) += time.o | 22 | //kbuild:lib-$(CONFIG_TIME) += time.o |
23 | 23 | ||
24 | //usage:#define time_trivial_usage | 24 | //usage:#define time_trivial_usage |
25 | //usage: IF_NOT_PLATFORM_MINGW32( | ||
25 | //usage: "[-vpa] [-o FILE] PROG ARGS" | 26 | //usage: "[-vpa] [-o FILE] PROG ARGS" |
27 | //usage: ) | ||
28 | //usage: IF_PLATFORM_MINGW32( | ||
29 | //usage: "[-pa] [-o FILE] PROG ARGS" | ||
30 | //usage: ) | ||
26 | //usage:#define time_full_usage "\n\n" | 31 | //usage:#define time_full_usage "\n\n" |
27 | //usage: "Run PROG, display resource usage when it exits\n" | 32 | //usage: "Run PROG, display resource usage when it exits\n" |
33 | //usage: IF_NOT_PLATFORM_MINGW32( | ||
28 | //usage: "\n -v Verbose" | 34 | //usage: "\n -v Verbose" |
35 | //usage: ) | ||
29 | //usage: "\n -p POSIX output format" | 36 | //usage: "\n -p POSIX output format" |
37 | //usage: IF_NOT_PLATFORM_MINGW32( | ||
30 | //usage: "\n -f FMT Custom format" | 38 | //usage: "\n -f FMT Custom format" |
39 | //usage: ) | ||
31 | //usage: "\n -o FILE Write result to FILE" | 40 | //usage: "\n -o FILE Write result to FILE" |
32 | //usage: "\n -a Append (else overwrite)" | 41 | //usage: "\n -a Append (else overwrite)" |
33 | 42 | ||
@@ -50,6 +59,7 @@ static const char default_format[] ALIGN1 = "real\t%E\nuser\t%u\nsys\t%T"; | |||
50 | /* The output format for the -p option .*/ | 59 | /* The output format for the -p option .*/ |
51 | static const char posix_format[] ALIGN1 = "real %e\nuser %U\nsys %S"; | 60 | static const char posix_format[] ALIGN1 = "real %e\nuser %U\nsys %S"; |
52 | 61 | ||
62 | #if !ENABLE_PLATFORM_MINGW32 | ||
53 | /* Format string for printing all statistics verbosely. | 63 | /* Format string for printing all statistics verbosely. |
54 | Keep this output to 24 lines so users on terminals can see it all.*/ | 64 | Keep this output to 24 lines so users on terminals can see it all.*/ |
55 | static const char long_format[] ALIGN1 = | 65 | static const char long_format[] ALIGN1 = |
@@ -76,6 +86,7 @@ static const char long_format[] ALIGN1 = | |||
76 | "\tSignals delivered: %k\n" | 86 | "\tSignals delivered: %k\n" |
77 | "\tPage size (bytes): %Z\n" | 87 | "\tPage size (bytes): %Z\n" |
78 | "\tExit status: %x"; | 88 | "\tExit status: %x"; |
89 | #endif | ||
79 | 90 | ||
80 | /* Wait for and fill in data on child process PID. | 91 | /* Wait for and fill in data on child process PID. |
81 | Return 0 on error, 1 if ok. */ | 92 | Return 0 on error, 1 if ok. */ |
@@ -86,7 +97,11 @@ static void resuse_end(pid_t pid, resource_t *resp) | |||
86 | 97 | ||
87 | /* Ignore signals, but don't ignore the children. When wait3 | 98 | /* Ignore signals, but don't ignore the children. When wait3 |
88 | * returns the child process, set the time the command finished. */ | 99 | * returns the child process, set the time the command finished. */ |
100 | #if !ENABLE_PLATFORM_MINGW32 | ||
89 | while ((caught = wait3(&resp->waitstatus, 0, &resp->ru)) != pid) { | 101 | while ((caught = wait3(&resp->waitstatus, 0, &resp->ru)) != pid) { |
102 | #else | ||
103 | while ((caught=mingw_wait3(pid, &resp->waitstatus, 0, &resp->ru)) != pid) { | ||
104 | #endif | ||
90 | if (caught == -1 && errno != EINTR) { | 105 | if (caught == -1 && errno != EINTR) { |
91 | bb_simple_perror_msg("wait"); | 106 | bb_simple_perror_msg("wait"); |
92 | return; | 107 | return; |
@@ -95,6 +110,7 @@ static void resuse_end(pid_t pid, resource_t *resp) | |||
95 | resp->elapsed_ms = monotonic_ms() - resp->elapsed_ms; | 110 | resp->elapsed_ms = monotonic_ms() - resp->elapsed_ms; |
96 | } | 111 | } |
97 | 112 | ||
113 | #if !ENABLE_PLATFORM_MINGW32 | ||
98 | static void printargv(char *const *argv) | 114 | static void printargv(char *const *argv) |
99 | { | 115 | { |
100 | const char *fmt = " %s" + 1; | 116 | const char *fmt = " %s" + 1; |
@@ -124,6 +140,7 @@ static unsigned long ptok(const unsigned pagesize, const unsigned long pages) | |||
124 | tmp = pages * pagesize; /* Larger first, */ | 140 | tmp = pages * pagesize; /* Larger first, */ |
125 | return tmp / 1024; /* then smaller. */ | 141 | return tmp / 1024; /* then smaller. */ |
126 | } | 142 | } |
143 | #endif | ||
127 | 144 | ||
128 | /* summarize: Report on the system use of a command. | 145 | /* summarize: Report on the system use of a command. |
129 | 146 | ||
@@ -173,11 +190,17 @@ static unsigned long ptok(const unsigned pagesize, const unsigned long pages) | |||
173 | #define TICKS_PER_SEC 100 | 190 | #define TICKS_PER_SEC 100 |
174 | #endif | 191 | #endif |
175 | 192 | ||
193 | #if ENABLE_PLATFORM_MINGW32 | ||
194 | #define summarize(f, c, r) summarize(f, r) | ||
195 | #endif | ||
196 | |||
176 | static void summarize(const char *fmt, char **command, resource_t *resp) | 197 | static void summarize(const char *fmt, char **command, resource_t *resp) |
177 | { | 198 | { |
199 | #if !ENABLE_PLATFORM_MINGW32 | ||
178 | unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */ | 200 | unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */ |
179 | unsigned cpu_ticks; /* Same, in "CPU ticks" */ | 201 | unsigned cpu_ticks; /* Same, in "CPU ticks" */ |
180 | unsigned pagesize = getpagesize(); | 202 | unsigned pagesize = getpagesize(); |
203 | #endif | ||
181 | 204 | ||
182 | /* Impossible: we do not use WUNTRACED flag in wait()... | 205 | /* Impossible: we do not use WUNTRACED flag in wait()... |
183 | if (WIFSTOPPED(resp->waitstatus)) | 206 | if (WIFSTOPPED(resp->waitstatus)) |
@@ -191,6 +214,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp) | |||
191 | printf("Command exited with non-zero status %u\n", | 214 | printf("Command exited with non-zero status %u\n", |
192 | WEXITSTATUS(resp->waitstatus)); | 215 | WEXITSTATUS(resp->waitstatus)); |
193 | 216 | ||
217 | #if !ENABLE_PLATFORM_MINGW32 | ||
194 | vv_ms = (resp->ru.ru_utime.tv_sec + resp->ru.ru_stime.tv_sec) * 1000 | 218 | vv_ms = (resp->ru.ru_utime.tv_sec + resp->ru.ru_stime.tv_sec) * 1000 |
195 | + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000; | 219 | + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000; |
196 | 220 | ||
@@ -201,6 +225,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp) | |||
201 | cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000; | 225 | cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000; |
202 | #endif | 226 | #endif |
203 | if (!cpu_ticks) cpu_ticks = 1; /* we divide by it, must be nonzero */ | 227 | if (!cpu_ticks) cpu_ticks = 1; /* we divide by it, must be nonzero */ |
228 | #endif | ||
204 | 229 | ||
205 | while (*fmt) { | 230 | while (*fmt) { |
206 | /* Handle leading literal part */ | 231 | /* Handle leading literal part */ |
@@ -234,6 +259,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp) | |||
234 | bb_putchar(*fmt); | 259 | bb_putchar(*fmt); |
235 | break; | 260 | break; |
236 | #endif | 261 | #endif |
262 | #if !ENABLE_PLATFORM_MINGW32 | ||
237 | case 'C': /* The command that got timed. */ | 263 | case 'C': /* The command that got timed. */ |
238 | printargv(command); | 264 | printargv(command); |
239 | break; | 265 | break; |
@@ -242,6 +268,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp) | |||
242 | (ptok(pagesize, (UL) resp->ru.ru_idrss) + | 268 | (ptok(pagesize, (UL) resp->ru.ru_idrss) + |
243 | ptok(pagesize, (UL) resp->ru.ru_isrss)) / cpu_ticks); | 269 | ptok(pagesize, (UL) resp->ru.ru_isrss)) / cpu_ticks); |
244 | break; | 270 | break; |
271 | #endif | ||
245 | case 'E': { /* Elapsed real (wall clock) time. */ | 272 | case 'E': { /* Elapsed real (wall clock) time. */ |
246 | unsigned seconds = resp->elapsed_ms / 1000; | 273 | unsigned seconds = resp->elapsed_ms / 1000; |
247 | if (seconds >= 3600) /* One hour -> h:m:s. */ | 274 | if (seconds >= 3600) /* One hour -> h:m:s. */ |
@@ -256,6 +283,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp) | |||
256 | (unsigned)(resp->elapsed_ms / 10) % 100); | 283 | (unsigned)(resp->elapsed_ms / 10) % 100); |
257 | break; | 284 | break; |
258 | } | 285 | } |
286 | #if !ENABLE_PLATFORM_MINGW32 | ||
259 | case 'F': /* Major page faults. */ | 287 | case 'F': /* Major page faults. */ |
260 | printf("%lu", resp->ru.ru_majflt); | 288 | printf("%lu", resp->ru.ru_majflt); |
261 | break; | 289 | break; |
@@ -284,6 +312,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp) | |||
284 | case 'R': /* Minor page faults (reclaims). */ | 312 | case 'R': /* Minor page faults (reclaims). */ |
285 | printf("%lu", resp->ru.ru_minflt); | 313 | printf("%lu", resp->ru.ru_minflt); |
286 | break; | 314 | break; |
315 | #endif | ||
287 | case 'S': /* System time. */ | 316 | case 'S': /* System time. */ |
288 | printf("%u.%02u", | 317 | printf("%u.%02u", |
289 | (unsigned)resp->ru.ru_stime.tv_sec, | 318 | (unsigned)resp->ru.ru_stime.tv_sec, |
@@ -318,6 +347,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp) | |||
318 | (unsigned)(resp->ru.ru_utime.tv_sec % 60), | 347 | (unsigned)(resp->ru.ru_utime.tv_sec % 60), |
319 | (unsigned)(resp->ru.ru_utime.tv_usec / 10000)); | 348 | (unsigned)(resp->ru.ru_utime.tv_usec / 10000)); |
320 | break; | 349 | break; |
350 | #if !ENABLE_PLATFORM_MINGW32 | ||
321 | case 'W': /* Times swapped out. */ | 351 | case 'W': /* Times swapped out. */ |
322 | printf("%lu", resp->ru.ru_nswap); | 352 | printf("%lu", resp->ru.ru_nswap); |
323 | break; | 353 | break; |
@@ -330,11 +360,13 @@ static void summarize(const char *fmt, char **command, resource_t *resp) | |||
330 | case 'c': /* Involuntary context switches. */ | 360 | case 'c': /* Involuntary context switches. */ |
331 | printf("%lu", resp->ru.ru_nivcsw); | 361 | printf("%lu", resp->ru.ru_nivcsw); |
332 | break; | 362 | break; |
363 | #endif | ||
333 | case 'e': /* Elapsed real time in seconds. */ | 364 | case 'e': /* Elapsed real time in seconds. */ |
334 | printf("%u.%02u", | 365 | printf("%u.%02u", |
335 | (unsigned)resp->elapsed_ms / 1000, | 366 | (unsigned)resp->elapsed_ms / 1000, |
336 | (unsigned)(resp->elapsed_ms / 10) % 100); | 367 | (unsigned)(resp->elapsed_ms / 10) % 100); |
337 | break; | 368 | break; |
369 | #if !ENABLE_PLATFORM_MINGW32 | ||
338 | case 'k': /* Signals delivered. */ | 370 | case 'k': /* Signals delivered. */ |
339 | printf("%lu", resp->ru.ru_nsignals); | 371 | printf("%lu", resp->ru.ru_nsignals); |
340 | break; | 372 | break; |
@@ -356,6 +388,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp) | |||
356 | case 'x': /* Exit status. */ | 388 | case 'x': /* Exit status. */ |
357 | printf("%u", WEXITSTATUS(resp->waitstatus)); | 389 | printf("%u", WEXITSTATUS(resp->waitstatus)); |
358 | break; | 390 | break; |
391 | #endif | ||
359 | } | 392 | } |
360 | break; | 393 | break; |
361 | 394 | ||
@@ -390,6 +423,7 @@ static void summarize(const char *fmt, char **command, resource_t *resp) | |||
390 | static void run_command(char *const *cmd, resource_t *resp) | 423 | static void run_command(char *const *cmd, resource_t *resp) |
391 | { | 424 | { |
392 | pid_t pid; | 425 | pid_t pid; |
426 | #if !ENABLE_PLATFORM_MINGW32 | ||
393 | void (*interrupt_signal)(int); | 427 | void (*interrupt_signal)(int); |
394 | void (*quit_signal)(int); | 428 | void (*quit_signal)(int); |
395 | 429 | ||
@@ -410,6 +444,13 @@ static void run_command(char *const *cmd, resource_t *resp) | |||
410 | /* Re-enable signals. */ | 444 | /* Re-enable signals. */ |
411 | signal(SIGINT, interrupt_signal); | 445 | signal(SIGINT, interrupt_signal); |
412 | signal(SIGQUIT, quit_signal); | 446 | signal(SIGQUIT, quit_signal); |
447 | #else | ||
448 | resp->elapsed_ms = monotonic_ms(); | ||
449 | if ((pid=spawn((char **)cmd)) == -1) | ||
450 | bb_perror_msg_and_die("can't execute %s", cmd[0]); | ||
451 | |||
452 | resuse_end(pid, resp); | ||
453 | #endif | ||
413 | } | 454 | } |
414 | 455 | ||
415 | int time_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; | 456 | int time_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE; |
@@ -423,20 +464,34 @@ int time_main(int argc UNUSED_PARAM, char **argv) | |||
423 | int opt; | 464 | int opt; |
424 | int ex; | 465 | int ex; |
425 | enum { | 466 | enum { |
467 | #if ENABLE_PLATFORM_MINGW32 | ||
426 | OPT_v = (1 << 0), | 468 | OPT_v = (1 << 0), |
427 | OPT_p = (1 << 1), | 469 | OPT_p = (1 << 1), |
428 | OPT_a = (1 << 2), | 470 | OPT_a = (1 << 2), |
429 | OPT_o = (1 << 3), | 471 | OPT_o = (1 << 3), |
430 | OPT_f = (1 << 4), | 472 | OPT_f = (1 << 4), |
473 | #else | ||
474 | OPT_p = (1 << 0), | ||
475 | OPT_a = (1 << 1), | ||
476 | OPT_o = (1 << 2), | ||
477 | #endif | ||
431 | }; | 478 | }; |
432 | 479 | ||
433 | /* "+": stop on first non-option */ | 480 | /* "+": stop on first non-option */ |
481 | #if !ENABLE_PLATFORM_MINGW32 | ||
434 | opt = getopt32(argv, "^+" "vpao:f:" "\0" "-1"/*at least one arg*/, | 482 | opt = getopt32(argv, "^+" "vpao:f:" "\0" "-1"/*at least one arg*/, |
435 | &output_filename, &output_format | 483 | &output_filename, &output_format |
436 | ); | 484 | ); |
485 | #else | ||
486 | opt = getopt32(argv, "^+" "pao:" "\0" "-1"/*at least one arg*/, | ||
487 | &output_filename | ||
488 | ); | ||
489 | #endif | ||
437 | argv += optind; | 490 | argv += optind; |
491 | #if !ENABLE_PLATFORM_MINGW32 | ||
438 | if (opt & OPT_v) | 492 | if (opt & OPT_v) |
439 | output_format = long_format; | 493 | output_format = long_format; |
494 | #endif | ||
440 | if (opt & OPT_p) | 495 | if (opt & OPT_p) |
441 | output_format = posix_format; | 496 | output_format = posix_format; |
442 | output_fd = STDERR_FILENO; | 497 | output_fd = STDERR_FILENO; |