time: -200 bytes of text
This commit is contained in:
parent
f93ab47c45
commit
c5cb38f4d9
180
miscutils/time.c
180
miscutils/time.c
@ -100,18 +100,14 @@ static int resuse_end(pid_t pid, resource_t * resp)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Print ARGV to FP, with each entry in ARGV separated by FILLER. */
|
||||
static void fprintargv(FILE * fp, char *const *argv, const char *filler)
|
||||
/* Print ARGV, with each entry in ARGV separated by FILLER. */
|
||||
static void printargv(char *const *argv, const char *filler)
|
||||
{
|
||||
char *const *av;
|
||||
|
||||
av = argv;
|
||||
fputs(*av, fp);
|
||||
while (*++av) {
|
||||
fputs(filler, fp);
|
||||
fputs(*av, fp);
|
||||
fputs(*argv, stdout);
|
||||
while (*++argv) {
|
||||
fputs(filler, stdout);
|
||||
fputs(*argv, stdout);
|
||||
}
|
||||
die_if_ferror(fp, "output");
|
||||
}
|
||||
|
||||
/* 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)
|
||||
|
||||
static unsigned long ptok(unsigned long pages)
|
||||
{
|
||||
static unsigned long ps = 0;
|
||||
static unsigned long ps;
|
||||
unsigned long tmp;
|
||||
static long size = LONG_MAX;
|
||||
|
||||
/* Initialization. */
|
||||
if (ps == 0)
|
||||
ps = (long) getpagesize();
|
||||
ps = getpagesize();
|
||||
|
||||
/* Conversion. */
|
||||
if (pages > (LONG_MAX / ps)) { /* Could overflow. */
|
||||
tmp = pages / 1024; /* Smaller first, */
|
||||
size = tmp * ps; /* then larger. */
|
||||
} else { /* Could underflow. */
|
||||
tmp = pages * ps; /* Larger first, */
|
||||
size = tmp / 1024; /* then smaller. */
|
||||
return tmp * ps; /* then larger. */
|
||||
}
|
||||
return size;
|
||||
/* Could underflow. */
|
||||
tmp = pages * ps; /* Larger first, */
|
||||
return tmp / 1024; /* then smaller. */
|
||||
}
|
||||
|
||||
/* summarize: Report on the system use of a command.
|
||||
|
||||
Copy the FMT argument to FP except that `%' sequences
|
||||
Print the FMT argument except that `%' sequences
|
||||
have special meaning, and `\n' and `\t' are translated into
|
||||
newline and tab, respectively, and `\\' is translated into `\'.
|
||||
|
||||
@ -183,25 +177,23 @@ static unsigned long ptok(unsigned long pages)
|
||||
to kbytes by multiplying by the page size, dividing by 1024,
|
||||
and dividing by elapsed real time.
|
||||
|
||||
FP is the stream to print to.
|
||||
FMT is the format string, interpreted as described above.
|
||||
COMMAND is the command and args that are being summarized.
|
||||
RESP is resource information on the command. */
|
||||
|
||||
static void summarize(FILE * fp, const char *fmt, char **command,
|
||||
resource_t * resp)
|
||||
static void summarize(const char *fmt, char **command, resource_t * resp)
|
||||
{
|
||||
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",
|
||||
printf("Command stopped by signal %d\n",
|
||||
WSTOPSIG(resp->waitstatus));
|
||||
else if (WIFSIGNALED(resp->waitstatus))
|
||||
fprintf(fp, "Command terminated by signal %d\n",
|
||||
printf("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",
|
||||
printf("Command exited with non-zero status %d\n",
|
||||
WEXITSTATUS(resp->waitstatus));
|
||||
|
||||
/* Convert all times to milliseconds. Occasionally, one of these values
|
||||
@ -214,178 +206,194 @@ static void summarize(FILE * fp, const char *fmt, char **command,
|
||||
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;
|
||||
|
||||
/* putchar() != putc(stdout) in glibc! */
|
||||
|
||||
while (*fmt) {
|
||||
/* Handle leading literal part */
|
||||
int n = strcspn(fmt, "%\\");
|
||||
if (n) {
|
||||
printf("%.*s", n, fmt);
|
||||
fmt += n;
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (*fmt) {
|
||||
#ifdef NOT_NEEDED
|
||||
/* Handle literal char */
|
||||
/* Usually we optimize for size, but there is a limit
|
||||
* for everything. With this we do a lot of 1-byte writes */
|
||||
default:
|
||||
putc(*fmt, stdout);
|
||||
break;
|
||||
#endif
|
||||
|
||||
case '%':
|
||||
switch (*++fmt) {
|
||||
case '%': /* Literal '%'. */
|
||||
putc('%', fp);
|
||||
#ifdef NOT_NEEDED_YET
|
||||
/* Our format strings do not have these */
|
||||
/* and we do not take format str from user */
|
||||
default:
|
||||
putc('%', stdout);
|
||||
/*FALLTHROUGH*/
|
||||
case '%':
|
||||
if (!*fmt) goto ret;
|
||||
putc(*fmt, stdout);
|
||||
break;
|
||||
#endif
|
||||
case 'C': /* The command that got timed. */
|
||||
fprintargv(fp, command, " ");
|
||||
printargv(command, " ");
|
||||
break;
|
||||
case 'D': /* Average unshared data size. */
|
||||
fprintf(fp, "%lu",
|
||||
printf("%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",
|
||||
printf("%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. */
|
||||
printf("%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);
|
||||
printf("%ld", resp->ru.ru_majflt);
|
||||
break;
|
||||
case 'I': /* Inputs. */
|
||||
fprintf(fp, "%ld", resp->ru.ru_inblock);
|
||||
printf("%ld", resp->ru.ru_inblock);
|
||||
break;
|
||||
case 'K': /* Average mem usage == data+stack+text. */
|
||||
fprintf(fp, "%lu",
|
||||
printf("%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));
|
||||
printf("%lu", ptok((UL) resp->ru.ru_maxrss));
|
||||
break;
|
||||
case 'O': /* Outputs. */
|
||||
fprintf(fp, "%ld", resp->ru.ru_oublock);
|
||||
printf("%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));
|
||||
printf("%lu%%", (v * 100 / r));
|
||||
else
|
||||
fprintf(fp, "?%%");
|
||||
printf("?%%");
|
||||
break;
|
||||
case 'R': /* Minor page faults (reclaims). */
|
||||
fprintf(fp, "%ld", resp->ru.ru_minflt);
|
||||
printf("%ld", resp->ru.ru_minflt);
|
||||
break;
|
||||
case 'S': /* System time. */
|
||||
fprintf(fp, "%ld.%02ld",
|
||||
printf("%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",
|
||||
printf("%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. */
|
||||
printf("%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",
|
||||
printf("%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",
|
||||
printf("%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. */
|
||||
printf("%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);
|
||||
printf("%ld", resp->ru.ru_nswap);
|
||||
break;
|
||||
case 'X': /* Average shared text size. */
|
||||
fprintf(fp, "%lu",
|
||||
printf("%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());
|
||||
printf("%d", getpagesize());
|
||||
break;
|
||||
case 'c': /* Involuntary context switches. */
|
||||
fprintf(fp, "%ld", resp->ru.ru_nivcsw);
|
||||
printf("%ld", resp->ru.ru_nivcsw);
|
||||
break;
|
||||
case 'e': /* Elapsed real time in seconds. */
|
||||
fprintf(fp, "%ld.%02ld",
|
||||
printf("%ld.%02ld",
|
||||
resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000);
|
||||
break;
|
||||
case 'k': /* Signals delivered. */
|
||||
fprintf(fp, "%ld", resp->ru.ru_nsignals);
|
||||
printf("%ld", resp->ru.ru_nsignals);
|
||||
break;
|
||||
case 'p': /* Average stack segment. */
|
||||
fprintf(fp, "%lu",
|
||||
printf("%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);
|
||||
printf("%ld", resp->ru.ru_msgrcv);
|
||||
break;
|
||||
case 's': /* Outgoing socket messages sent. */
|
||||
fprintf(fp, "%ld", resp->ru.ru_msgsnd);
|
||||
printf("%ld", resp->ru.ru_msgsnd);
|
||||
break;
|
||||
case 't': /* Average resident set size. */
|
||||
fprintf(fp, "%lu",
|
||||
printf("%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);
|
||||
printf("%ld", resp->ru.ru_nvcsw);
|
||||
break;
|
||||
case 'x': /* Exit status. */
|
||||
fprintf(fp, "%d", WEXITSTATUS(resp->waitstatus));
|
||||
printf("%d", WEXITSTATUS(resp->waitstatus));
|
||||
break;
|
||||
case '\0':
|
||||
putc('?', fp);
|
||||
return;
|
||||
default:
|
||||
putc('?', fp);
|
||||
putc(*fmt, fp);
|
||||
}
|
||||
++fmt;
|
||||
break;
|
||||
|
||||
#ifdef NOT_NEEDED_YET
|
||||
case '\\': /* Format escape. */
|
||||
switch (*++fmt) {
|
||||
default:
|
||||
putc('\\', stdout);
|
||||
/*FALLTHROUGH*/
|
||||
case '\\':
|
||||
if (!*fmt) goto ret;
|
||||
putc(*fmt, stdout);
|
||||
break;
|
||||
case 't':
|
||||
putc('\t', fp);
|
||||
putc('\t', stdout);
|
||||
break;
|
||||
case 'n':
|
||||
putc('\n', fp);
|
||||
putc('\n', stdout);
|
||||
break;
|
||||
case '\\':
|
||||
putc('\\', fp);
|
||||
break;
|
||||
default:
|
||||
putc('?', fp);
|
||||
putc('\\', fp);
|
||||
putc(*fmt, fp);
|
||||
}
|
||||
++fmt;
|
||||
break;
|
||||
|
||||
default:
|
||||
putc(*fmt++, fp);
|
||||
#endif
|
||||
}
|
||||
|
||||
die_if_ferror(fp, "output");
|
||||
++fmt;
|
||||
}
|
||||
putc('\n', fp);
|
||||
|
||||
die_if_ferror(fp, "output");
|
||||
/* ret: */
|
||||
putc('\n', stdout);
|
||||
}
|
||||
|
||||
/* Run command CMD and return statistics on it.
|
||||
@ -449,7 +457,11 @@ int time_main(int argc, char **argv)
|
||||
}
|
||||
|
||||
run_command(argv, &res);
|
||||
summarize(stderr, output_format, argv, &res);
|
||||
|
||||
/* Cheat. printf's are shorter :) */
|
||||
stdout = stderr;
|
||||
dup2(2, 1); /* just in case libc does something silly :( */
|
||||
summarize(output_format, argv, &res);
|
||||
|
||||
if (WIFSTOPPED(res.waitstatus))
|
||||
return WSTOPSIG(res.waitstatus);
|
||||
@ -457,5 +469,5 @@ int time_main(int argc, char **argv)
|
||||
return WTERMSIG(res.waitstatus);
|
||||
if (WIFEXITED(res.waitstatus))
|
||||
return WEXITSTATUS(res.waitstatus);
|
||||
return 0;
|
||||
fflush_stdout_and_exit(0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user