Makefile.am | 4 +-- Makefile.in | 6 ++-- README | 2 +- configure.in | 14 ++++----- resuse.c | 3 ++ resuse.h | 15 ++-------- time.c | 94 ++++++++++++++++++++++++++++-------------------------------- time.texi | 65 ++++++++++++++++++++--------------------- version.texi | 2 +- 9 files changed, 96 insertions(+), 109 deletions(-) diff --git a/Makefile.am b/Makefile.am index 1dbf7d7..3c494c7 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,7 +1,7 @@ bin_PROGRAMS = time info_TEXINFOS = time.texi -time_SOURCES = time.c getopt.c getopt1.c error.c resuse.c version.c \ - getopt.h getpagesize.h resuse.h port.h wait.h +time_SOURCES = time.c resuse.c version.c \ + getpagesize.h resuse.h port.h EXTRA_DIST = texinfo.tex DISTCLEANFILES = stamp-v version.c diff --git a/Makefile.in b/Makefile.in index 7ee5080..f5b2e96 100644 --- a/Makefile.in +++ b/Makefile.in @@ -40,8 +40,8 @@ transform = @program_transform_name@ bin_PROGRAMS = time info_TEXINFOS = time.texi -time_SOURCES = time.c getopt.c getopt1.c error.c resuse.c version.c \ - getopt.h getpagesize.h resuse.h port.h wait.h +time_SOURCES = time.c resuse.c version.c \ + getpagesize.h resuse.h port.h wait.h EXTRA_DIST = texinfo.tex DISTCLEANFILES = stamp-v version.c @@ -61,7 +61,7 @@ LIBS = @LIBS@ COMPILE = $(CC) -c $(DEFS) $(INCLUDES) $(CPPFLAGS) $(CFLAGS) LINK = $(CC) $(LDFLAGS) -o $@ -time_OBJECTS = time.o getopt.o getopt1.o error.o resuse.o version.o +time_OBJECTS = time.o resuse.o version.o EXTRA_time_SOURCES = time_LDADD = $(LDADD) diff --git a/README b/README index 35e4938..43f294f 100644 --- a/README +++ b/README @@ -8,6 +8,6 @@ unavailable information as zero values. See the file INSTALL for compilation and installation instructions. Mail suggestions and bug reports for GNU time to -bug-gnu-utils@prep.ai.mit.edu. Please include the version of +bug-gnu-utils@gnu.org. Please include the version of `time', which you can get by running `time --version', and the operating system and C compiler you used. diff --git a/configure.in b/configure.in index 1531bad..6afdd49 100644 --- a/configure.in +++ b/configure.in @@ -1,21 +1,19 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(time.c) -VERSION=1.7 -AC_SUBST(VERSION) -PACKAGE=time -AC_SUBST(PACKAGE) - -AC_ARG_PROGRAM +AM_INIT_AUTOMAKE(time, 1.7) dnl Checks for programs. AC_PROG_CC AC_PROG_CPP AC_PROG_INSTALL +dnl Enable LFS API. +AC_SYS_LARGEFILE + dnl Checks for header files. AC_HEADER_STDC AC_HEADER_SYS_WAIT -AC_CHECK_HEADERS(unistd.h string.h sys/rusage.h) +AC_CHECK_HEADERS(unistd.h string.h sys/rusage.h sys/resource.h time.h) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST @@ -31,7 +29,7 @@ test $have_tv = yes && AC_DEFINE(HAVE_TIMEVAL) dnl Checks for library functions. AC_FUNC_VPRINTF AC_FUNC_WAIT3 -AC_CHECK_FUNCS(strerror) +AC_CHECK_FUNCS(strerror wait3) AC_MSG_CHECKING(for getpagesize) AC_TRY_LINK([#include ], diff --git a/resuse.c b/resuse.c index 4133941..410c86b 100644 --- a/resuse.c +++ b/resuse.c @@ -25,6 +25,9 @@ #if !HAVE_WAIT3 # include +# if HAVE_TIME_H +# include +# endif # ifndef HZ # include # endif diff --git a/resuse.h b/resuse.h index 992143f..fdc8b8d 100644 --- a/resuse.h +++ b/resuse.h @@ -33,22 +33,13 @@ struct timeval #if HAVE_SYS_RUSAGE_H /* This rusage structure measures nanoseconds instead of microseconds. */ # define TV_MSEC tv_nsec / 1000000 +# define TV_USEC tv_nsec / 1000 # include #else # define TV_MSEC tv_usec / 1000 -# if HAVE_WAIT3 +# define TV_USEC tv_usec +# if HAVE_SYS_RESOURCE_H # include -# else -/* Process resource usage structure. */ -struct rusage -{ - struct timeval ru_utime; /* User time used. */ - struct timeval ru_stime; /* System time used. */ - int ru_maxrss, ru_ixrss, ru_idrss, ru_isrss, - ru_minflt, ru_majflt, ru_nswap, ru_inblock, - ru_oublock, ru_msgsnd, ru_msgrcv, ru_nsignals, - ru_nvcsw, ru_nivcsw; -}; # endif #endif diff --git a/time.c b/time.c index 9d5cf2c..d858c0d 100644 --- a/time.c +++ b/time.c @@ -147,6 +147,10 @@ static const char *const longstats[] = NULL }; + +/* If true, do not show the exit message */ +static boolean quiet; + /* If true, show an English description next to each statistic. */ static boolean verbose; @@ -172,6 +176,7 @@ static struct option longopts[] = {"help", no_argument, NULL, 'h'}, {"output-file", required_argument, NULL, 'o'}, {"portability", no_argument, NULL, 'p'}, + {"quiet", no_argument, NULL, 'q'}, {"verbose", no_argument, NULL, 'v'}, {"version", no_argument, NULL, 'V'}, {NULL, no_argument, NULL, 0} @@ -240,39 +245,6 @@ linear_argv (argv) return new; } -/* Return the number of kilobytes corresponding to a number of pages PAGES. - (Actually, we use it to convert pages*ticks into kilobytes*ticks.) - - Try to do arithmetic so that the risk of overflow errors is minimized. - This is funky since the pagesize could be less than 1K. - Note: Some machines express getrusage statistics in terms of K, - others in terms of pages. */ - -static unsigned long -ptok (pages) - unsigned long pages; -{ - static unsigned long ps = 0; - unsigned long tmp; - static long size = LONG_MAX; - - /* Initialization. */ - if (ps == 0) - ps = (long) 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 size; -} /* summarize: Report on the system use of a command. @@ -326,6 +298,8 @@ summarize (fp, fmt, command, resp) { unsigned long r; /* Elapsed real milliseconds. */ unsigned long v; /* Elapsed virtual (CPU) milliseconds. */ + unsigned long ru; /* Elapsed real microseconds. */ + unsigned long vu; /* Elapsed virtual (CPU) microseconds. */ if (WIFSTOPPED (resp->waitstatus)) fprintf (fp, "Command stopped by signal %d\n", @@ -333,7 +307,8 @@ summarize (fp, fmt, command, resp) else if (WIFSIGNALED (resp->waitstatus)) fprintf (fp, "Command terminated by signal %d\n", WTERMSIG (resp->waitstatus)); - else if (WIFEXITED (resp->waitstatus) && WEXITSTATUS (resp->waitstatus)) + else if (WIFEXITED (resp->waitstatus) && WEXITSTATUS (resp->waitstatus) + && !quiet) fprintf (fp, "Command exited with non-zero status %d\n", WEXITSTATUS (resp->waitstatus)); @@ -347,6 +322,17 @@ summarize (fp, fmt, command, resp) 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; + if (r == 0 && v == 0) + { + ru = resp->elapsed.tv_usec; + vu = resp->ru.ru_utime.TV_USEC + resp->ru.ru_stime.TV_USEC; + } + else + { + ru = 0; + vu = 0; + } + while (*fmt) { switch (*fmt) @@ -363,8 +349,8 @@ summarize (fp, fmt, command, resp) 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)); + resp->ru.ru_idrss / MSEC_TO_TICKS (v) + + 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. */ @@ -387,12 +373,12 @@ summarize (fp, fmt, command, resp) 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)); + resp->ru.ru_idrss / MSEC_TO_TICKS (v) + + resp->ru.ru_isrss / MSEC_TO_TICKS (v) + + resp->ru.ru_ixrss / MSEC_TO_TICKS (v)); break; case 'M': /* Maximum resident set size. */ - fprintf (fp, "%lu", ptok ((UL) resp->ru.ru_maxrss)); + fprintf (fp, "%lu", resp->ru.ru_maxrss); break; case 'O': /* Outputs. */ fprintf (fp, "%ld", resp->ru.ru_oublock); @@ -401,6 +387,8 @@ summarize (fp, fmt, command, resp) /* % cpu is (total cpu time)/(elapsed time). */ if (r > 0) fprintf (fp, "%lu%%", (v * 100 / r)); + else if (ru > 0) + fprintf (fp, "%lu%%", (vu * 100 / ru)); else fprintf (fp, "?%%"); break; @@ -423,7 +411,7 @@ summarize (fp, fmt, command, resp) 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)); + resp->ru.ru_ixrss / MSEC_TO_TICKS (v)); break; case 'Z': /* Page size. */ fprintf (fp, "%d", getpagesize ()); @@ -442,7 +430,7 @@ summarize (fp, fmt, command, resp) case 'p': /* Average stack segment. */ fprintf (fp, "%lu", MSEC_TO_TICKS (v) == 0 ? 0 : - ptok ((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS (v)); + resp->ru.ru_isrss / MSEC_TO_TICKS (v)); break; case 'r': /* Incoming socket messages received. */ fprintf (fp, "%ld", resp->ru.ru_msgrcv); @@ -453,7 +441,7 @@ summarize (fp, fmt, command, resp) 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)); + resp->ru.ru_idrss / MSEC_TO_TICKS (v)); break; case 'w': /* Voluntary context switches. */ fprintf (fp, "%ld", resp->ru.ru_nvcsw); @@ -523,6 +511,7 @@ getargs (argc, argv) char *format; /* Format found in environment. */ /* Initialize the option flags. */ + quiet = false; verbose = false; outfile = NULL; outfp = stderr; @@ -536,7 +525,7 @@ getargs (argc, argv) if (format) output_format = format; - while ((optc = getopt_long (argc, argv, "+af:o:pvV", longopts, (int *) 0)) + while ((optc = getopt_long (argc, argv, "+af:o:pqvV", longopts, (int *) 0)) != EOF) { switch (optc) @@ -555,6 +544,9 @@ getargs (argc, argv) case 'p': output_format = posix_format; break; + case 'q': + quiet = true; + break; case 'v': verbose = true; break; @@ -628,7 +620,7 @@ run_command (cmd, resp) signal (SIGQUIT, quit_signal); } -void +int main (argc, argv) int argc; char **argv; @@ -637,16 +629,18 @@ main (argc, argv) RESUSE res; command_line = getargs (argc, argv); - run_command (command_line, &res); + run_command ((char *const *)command_line, &res); summarize (outfp, output_format, command_line, &res); fflush (outfp); if (WIFSTOPPED (res.waitstatus)) - exit (WSTOPSIG (res.waitstatus)); + return WSTOPSIG (res.waitstatus) + 128; else if (WIFSIGNALED (res.waitstatus)) - exit (WTERMSIG (res.waitstatus)); + return WTERMSIG (res.waitstatus) + 128; else if (WIFEXITED (res.waitstatus)) - exit (WEXITSTATUS (res.waitstatus)); + return WEXITSTATUS (res.waitstatus); + else + return 0; } static void @@ -657,7 +651,7 @@ usage (stream, status) fprintf (stream, "\ Usage: %s [-apvV] [-f format] [-o file] [--append] [--verbose]\n\ [--portability] [--format=format] [--output=file] [--version]\n\ - [--help] command [arg...]\n", + [--quiet] [--help] command [arg...]\n", program_name); exit (status); } diff --git a/time.texi b/time.texi index 8d5af92..add0bb7 100644 --- a/time.texi +++ b/time.texi @@ -12,6 +12,11 @@ @end iftex @ifinfo +@dircategory Individual utilities +@direntry +* time: (time). Run programs and summarize + system resource usage. +@end direntry This file documents the the GNU @code{time} command for running programs and summarizing the system resources they use. @@ -64,7 +69,10 @@ except that this permission notice may be stated in a translation approved by the Foundation. @end titlepage -@node Top, , (dir), (dir) +@contents + +@node Top +@top The GNU @code{time} Command @ifinfo This file documents the the GNU @code{time} command for running programs @@ -74,30 +82,12 @@ This is edition @value{EDITION}, for version @value{VERSION}. @menu * Resource Measurement:: Measuring program resource use. - - --- The Detailed Node Listing --- - -Measuring Program Resource Use - -* Setting Format:: Selecting the information reported by @code{time}. -* Format String:: The information @code{time} can report. -* Redirecting:: Writing the information to a file. -* Examples:: Examples of using @code{time}. -* Accuracy:: Limitations on the accuracy of @code{time} output. -* Invoking time:: Summary of the options to the @code{time} command. - -The Format String - -* Time Resources:: -* Memory Resources:: -* I/O Resources:: -* Command Info:: +* Concept index:: Index of concepts. @end menu -@node Resource Measurement, , , Top +@node Resource Measurement @chapter Measuring Program Resource Use -@findex time -@kindex time +@cindex time invocation @pindex time @pindex measurement @@ -119,7 +109,7 @@ The format of the @code{time} command is: time @r{[}option@dots{}@r{]} @var{command} @r{[}@var{arg}@dots{}@r{]} @end example -@kindex resources +@cindex resource specifiers @code{time} runs the program @var{command}, with any given arguments @var{arg}@dots{}. When @var{command} finishes, @code{time} displays information about resources used by @var{command}. @@ -137,7 +127,7 @@ misc-group:nobody @end example Mail suggestions and bug reports for GNU @code{time} to -@code{bug-gnu-utils@@prep.ai.mit.edu}. Please include the version of +@code{bug-gnu-utils@@gnu.org}. Please include the version of @code{time}, which you can get by running @samp{time --version}, and the operating system and C compiler you used. @@ -176,8 +166,7 @@ Use @var{format} as the format string. @item -p @itemx --portability -Use the following format string, for conformance with POSIX standard -1003.2: +Use the following format string: @example real %e @@ -185,9 +174,18 @@ user %U sys %S @end example +The default output format of time differs widely between +implementations. This option (in its short form -p) is supported by all +POSIX-compliant 'time' implementations to retrieve basic information in +the described format. + +@item -q +@itemx --quiet +Suppress non-zero error code from the executed program. + @item -v @itemx --verbose -@cindex format +@cindex verbose format Use the built-in verbose format, which displays each available piece of information on the program's resource use on its own line, with an English description of its meaning. @@ -197,7 +195,6 @@ English description of its meaning. @section The Format String @cindex format -@kindex resource The @dfn{format string} controls the contents of the @code{time} output. It consists of @dfn{resource specifiers} and @dfn{escapes}, interspersed with plain text. @@ -440,7 +437,7 @@ eg$ time -v sleep 4 @node Accuracy @section Accuracy -@kindex error (in measurement) +@cindex error (in measurement) The elapsed time is not collected atomically with the execution of the program; as a result, in bizarre circumstances (if the @code{time} @@ -479,7 +476,7 @@ The format of the @code{time} command is: time @r{[}option@dots{}@r{]} @var{command} @r{[}@var{arg}@dots{}@r{]} @end example -@kindex resources +@cindex resources @code{time} runs the program @var{command}, with any given arguments @var{arg}@dots{}. When @var{command} finishes, @code{time} displays information about resources used by @var{command} (on the standard error @@ -514,7 +511,7 @@ Use the POSIX format. @item -v @itemx --verbose -@cindex format +@cindex verbose option Use the built-in verbose format. @item -V @@ -523,5 +520,9 @@ Use the built-in verbose format. Print the version number of @code{time} and exit. @end table -@contents +@node Concept index +@unnumbered Concept index + +@printindex cp + @bye diff --git a/version.texi b/version.texi index ef9acdc..2d46fc1 100644 --- a/version.texi +++ b/version.texi @@ -1,3 +1,3 @@ -@set UPDATED 12 June 1996 +@set UPDATED 9 May 2002 @set EDITION 1.7 @set VERSION 1.7