- unsigned long r; /* Elapsed real milliseconds. */
- unsigned long v; /* Elapsed virtual (CPU) milliseconds. */
-
- if (WIFSTOPPED (resp->waitstatus))
- fprintf (fp, "Command stopped by signal %d\n", WSTOPSIG (resp->waitstatus));
- else if (WIFSIGNALED (resp->waitstatus))
- fprintf (fp, "Command terminated by signal %d\n", WTERMSIG (resp->waitstatus));
- else if (WIFEXITED (resp->waitstatus) && WEXITSTATUS (resp->waitstatus))
- fprintf (fp, "Command exited with non-zero status %d\n", WEXITSTATUS (resp->waitstatus));
-
- /* Convert all times to milliseconds. Occasionally, one of these values
- comes out as zero. Dividing by zero causes problems, so we first
- check the time value. If it is zero, then we take `evasive action'
- instead of calculating a value. */
-
- r = resp->elapsed.tv_sec * 1000 + resp->elapsed.tv_usec / 1000;
-
- v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC +
- resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC;
-
- while (*fmt)
- {
- switch (*fmt)
- {
- case '%':
- switch (*++fmt)
- {
- case '%': /* Literal '%'. */
- putc ('%', fp);
- break;
- case 'C': /* The command that got timed. */
- fprintargv (fp, command, " ");
- break;
- case 'D': /* Average unshared data size. */
- fprintf (fp, "%lu",
- MSEC_TO_TICKS (v) == 0 ? 0 :
- ptok ((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS (v) +
- ptok ((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS (v));
- break;
- case 'E': /* Elapsed real (wall clock) time. */
- if (resp->elapsed.tv_sec >= 3600) /* One hour -> h:m:s. */
- fprintf (fp, "%ldh %ldm %02lds",
- resp->elapsed.tv_sec / 3600,
- (resp->elapsed.tv_sec % 3600) / 60,
- resp->elapsed.tv_sec % 60);
- else
- fprintf (fp, "%ldm %ld.%02lds", /* -> m:s. */
- resp->elapsed.tv_sec / 60,
- resp->elapsed.tv_sec % 60,
- resp->elapsed.tv_usec / 10000);
- break;
- case 'F': /* Major page faults. */
- fprintf (fp, "%ld", resp->ru.ru_majflt);
- break;
- case 'I': /* Inputs. */
- fprintf (fp, "%ld", resp->ru.ru_inblock);
- break;
- case 'K': /* Average mem usage == data+stack+text. */
- fprintf (fp, "%lu",
- MSEC_TO_TICKS (v) == 0 ? 0 :
- ptok ((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS (v) +
- ptok ((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS (v) +
- ptok ((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS (v));
- break;
- case 'M': /* Maximum resident set size. */
- fprintf (fp, "%lu", ptok ((UL) resp->ru.ru_maxrss));
- break;
- case 'O': /* Outputs. */
- fprintf (fp, "%ld", resp->ru.ru_oublock);
- break;
- case 'P': /* Percent of CPU this job got. */
- /* % cpu is (total cpu time)/(elapsed time). */
- if (r > 0)
- fprintf (fp, "%lu%%", (v * 100 / r));
- else
- fprintf (fp, "?%%");
- break;
- case 'R': /* Minor page faults (reclaims). */
- fprintf (fp, "%ld", resp->ru.ru_minflt);
- break;
- case 'S': /* System time. */
- fprintf (fp, "%ld.%02ld",
- resp->ru.ru_stime.tv_sec,
- resp->ru.ru_stime.TV_MSEC / 10);
- break;
- case 'T': /* System time. */
- if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s. */
- fprintf (fp, "%ldh %ldm %02lds",
- resp->ru.ru_stime.tv_sec / 3600,
- (resp->ru.ru_stime.tv_sec % 3600) / 60,
- resp->ru.ru_stime.tv_sec % 60);
- else
- fprintf (fp, "%ldm %ld.%02lds", /* -> m:s. */
- resp->ru.ru_stime.tv_sec / 60,
- resp->ru.ru_stime.tv_sec % 60,
- resp->ru.ru_stime.tv_usec / 10000);
- break;
- case 'U': /* User time. */
- fprintf (fp, "%ld.%02ld",
- resp->ru.ru_utime.tv_sec,
- resp->ru.ru_utime.TV_MSEC / 10);
- break;
- case 'u': /* User time. */
- if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s. */
- fprintf (fp, "%ldh %ldm %02lds",
- resp->ru.ru_utime.tv_sec / 3600,
- (resp->ru.ru_utime.tv_sec % 3600) / 60,
- resp->ru.ru_utime.tv_sec % 60);
- else
- fprintf (fp, "%ldm %ld.%02lds", /* -> m:s. */
- resp->ru.ru_utime.tv_sec / 60,
- resp->ru.ru_utime.tv_sec % 60,
- resp->ru.ru_utime.tv_usec / 10000);
- break;
- case 'W': /* Times swapped out. */
- fprintf (fp, "%ld", resp->ru.ru_nswap);
- break;
- case 'X': /* Average shared text size. */
- fprintf (fp, "%lu",
- MSEC_TO_TICKS (v) == 0 ? 0 :
- ptok ((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS (v));
- break;
- case 'Z': /* Page size. */
- fprintf (fp, "%d", getpagesize ());
- break;
- case 'c': /* Involuntary context switches. */
- fprintf (fp, "%ld", resp->ru.ru_nivcsw);
- break;
- case 'e': /* Elapsed real time in seconds. */
- fprintf (fp, "%ld.%02ld",
- resp->elapsed.tv_sec,
- resp->elapsed.tv_usec / 10000);
- break;
- case 'k': /* Signals delivered. */
- fprintf (fp, "%ld", resp->ru.ru_nsignals);
- break;
- case 'p': /* Average stack segment. */
- fprintf (fp, "%lu",
- MSEC_TO_TICKS (v) == 0 ? 0 :
- ptok ((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS (v));
- break;
- case 'r': /* Incoming socket messages received. */
- fprintf (fp, "%ld", resp->ru.ru_msgrcv);
- break;
- case 's': /* Outgoing socket messages sent. */
- fprintf (fp, "%ld", resp->ru.ru_msgsnd);
- break;
- case 't': /* Average resident set size. */
- fprintf (fp, "%lu",
- MSEC_TO_TICKS (v) == 0 ? 0 :
- ptok ((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS (v));
- break;
- case 'w': /* Voluntary context switches. */
- fprintf (fp, "%ld", resp->ru.ru_nvcsw);
- break;
- case 'x': /* Exit status. */
- fprintf (fp, "%d", WEXITSTATUS (resp->waitstatus));
- break;
- case '\0':
- putc ('?', fp);
- return;
- default:
- putc ('?', fp);
- putc (*fmt, fp);
+ unsigned vv_ms; /* Elapsed virtual (CPU) milliseconds */
+ unsigned cpu_ticks; /* Same, in "CPU ticks" */
+ unsigned pagesize = getpagesize();
+
+ /* Impossible: we do not use WUNTRACED flag in wait()...
+ if (WIFSTOPPED(resp->waitstatus))
+ printf("Command stopped by signal %u\n",
+ WSTOPSIG(resp->waitstatus));
+ else */
+ if (WIFSIGNALED(resp->waitstatus))
+ printf("Command terminated by signal %u\n",
+ WTERMSIG(resp->waitstatus));
+ else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus))
+ printf("Command exited with non-zero status %u\n",
+ WEXITSTATUS(resp->waitstatus));
+
+ vv_ms = (resp->ru.ru_utime.tv_sec + resp->ru.ru_stime.tv_sec) * 1000
+ + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000;
+
+#if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000
+ /* 1000 is exactly divisible by TICKS_PER_SEC (typical) */
+ cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC);
+#else
+ cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000;
+#endif
+ if (!cpu_ticks) cpu_ticks = 1; /* we divide by it, must be nonzero */
+
+ while (*fmt) {
+ /* Handle leading literal part */
+ int n = strcspn(fmt, "%\\");
+ if (n) {
+ printf("%.*s", n, fmt);
+ fmt += n;
+ continue;