Ignore:
Timestamp:
Nov 4, 2007, 3:16:40 AM (16 years ago)
Author:
Bruno Cornec
Message:

Update to busybox 1.7.2

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/2.2.5/mindi-busybox/miscutils/time.c

    r821 r1765  
    33   Copyright (C) 1990, 91, 92, 93, 96 Free Software Foundation, Inc.
    44
    5    Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
     5   Licensed under GPL version 2, see file LICENSE in this tarball for details.
    66*/
    77/* Originally written by David Keppel <pardo@cs.washington.edu>.
     
    1010*/
    1111
    12 #include "busybox.h"
    13 #include <stdlib.h>
    14 #include <stdio.h>
    15 #include <signal.h>
    16 #include <errno.h>
    17 #include <getopt.h>
    18 #include <string.h>
    19 #include <limits.h>
    20 #include <unistd.h>
    21 #include <sys/types.h>  /* For pid_t. */
    22 #include <sys/wait.h>
    23 #include <sys/param.h>  /* For getpagesize, maybe.  */
    24 
    25 #define TV_MSEC tv_usec / 1000
    26 #include <sys/resource.h>
     12#include "libbb.h"
    2713
    2814/* Information on the resources used by a child process.  */
     
    3016    int waitstatus;
    3117    struct rusage ru;
    32     struct timeval start, elapsed;  /* Wallclock time of process.  */
     18    unsigned elapsed_ms;    /* Wallclock time of process.  */
    3319} resource_t;
    3420
     
    3622   usec = microseconds = 1/1,000,000 (1*10e-6) second.  */
    3723
    38 #ifndef TICKS_PER_SEC
    39 #define TICKS_PER_SEC 100
    40 #endif
    41 
    42 /* The number of milliseconds in one `tick' used by the `rusage' structure.  */
    43 #define MSEC_PER_TICK (1000 / TICKS_PER_SEC)
    44 
    45 /* Return the number of clock ticks that occur in M milliseconds.  */
    46 #define MSEC_TO_TICKS(m) ((m) / MSEC_PER_TICK)
    47 
    4824#define UL unsigned long
    4925
    50 static const char *const default_format = "real\t%E\nuser\t%u\nsys\t%T";
     26static const char default_format[] ALIGN1 = "real\t%E\nuser\t%u\nsys\t%T";
    5127
    5228/* The output format for the -p option .*/
    53 static const char *const posix_format = "real %e\nuser %U\nsys %S";
     29static const char posix_format[] ALIGN1 = "real %e\nuser %U\nsys %S";
    5430
    5531
    5632/* Format string for printing all statistics verbosely.
    5733   Keep this output to 24 lines so users on terminals can see it all.*/
    58 static const char *const long_format =
     34static const char long_format[] ALIGN1 =
    5935    "\tCommand being timed: \"%C\"\n"
    6036    "\tUser time (seconds): %U\n"
     
    7854    "\tSocket messages received: %r\n"
    7955    "\tSignals delivered: %k\n"
    80     "\tPage size (bytes): %Z\n" "\tExit status: %x";
    81 
    82 
    83   /* Wait for and fill in data on child process PID.
    84      Return 0 on error, 1 if ok.  */
     56    "\tPage size (bytes): %Z\n"
     57    "\tExit status: %x";
     58
     59
     60/* Wait for and fill in data on child process PID.
     61   Return 0 on error, 1 if ok.  */
    8562
    8663/* pid_t is short on BSDI, so don't try to promote it.  */
     
    8865{
    8966    int status;
    90 
    9167    pid_t caught;
    9268
     
    9773            return 0;
    9874    }
    99 
    100     gettimeofday(&resp->elapsed, (struct timezone *) 0);
    101     resp->elapsed.tv_sec -= resp->start.tv_sec;
    102     if (resp->elapsed.tv_usec < resp->start.tv_usec) {
    103         /* Manually carry a one from the seconds field.  */
    104         resp->elapsed.tv_usec += 1000000;
    105         --resp->elapsed.tv_sec;
    106     }
    107     resp->elapsed.tv_usec -= resp->start.tv_usec;
    108 
     75    resp->elapsed_ms = (monotonic_us() / 1000) - resp->elapsed_ms;
    10976    resp->waitstatus = status;
    110 
    11177    return 1;
    11278}
    11379
    114 /* Print ARGV to FP, with each entry in ARGV separated by FILLER.  */
    115 static void fprintargv(FILE * fp, char *const *argv, const char *filler)
    116 {
    117     char *const *av;
    118 
    119     av = argv;
    120     fputs(*av, fp);
    121     while (*++av) {
    122         fputs(filler, fp);
    123         fputs(*av, fp);
    124     }
    125     if (ferror(fp))
    126         bb_error_msg_and_die(bb_msg_write_error);
     80/* Print ARGV, with each entry in ARGV separated by FILLER.  */
     81static void printargv(char *const *argv, const char *filler)
     82{
     83    fputs(*argv, stdout);
     84    while (*++argv) {
     85        fputs(filler, stdout);
     86        fputs(*argv, stdout);
     87    }
    12788}
    12889
     
    13798static unsigned long ptok(unsigned long pages)
    13899{
    139     static unsigned long ps = 0;
     100    static unsigned long ps;
    140101    unsigned long tmp;
    141     static long size = LONG_MAX;
    142102
    143103    /* Initialization.  */
    144104    if (ps == 0)
    145         ps = (long) getpagesize();
     105        ps = getpagesize();
    146106
    147107    /* Conversion.  */
    148108    if (pages > (LONG_MAX / ps)) {  /* Could overflow.  */
    149109        tmp = pages / 1024; /* Smaller first, */
    150         size = tmp * ps;    /* then larger.  */
    151     } else {            /* Could underflow.  */
    152         tmp = pages * ps;   /* Larger first, */
    153         size = tmp / 1024;  /* then smaller.  */
    154     }
    155     return size;
     110        return tmp * ps;    /* then larger.  */
     111    }
     112    /* Could underflow.  */
     113    tmp = pages * ps;   /* Larger first, */
     114    return tmp / 1024;  /* then smaller.  */
    156115}
    157116
    158117/* summarize: Report on the system use of a command.
    159118
    160    Copy the FMT argument to FP except that `%' sequences
     119   Print the FMT argument except that `%' sequences
    161120   have special meaning, and `\n' and `\t' are translated into
    162121   newline and tab, respectively, and `\\' is translated into `\'.
     
    196155   and dividing by elapsed real time.
    197156
    198    FP is the stream to print to.
    199157   FMT is the format string, interpreted as described above.
    200158   COMMAND is the command and args that are being summarized.
    201159   RESP is resource information on the command.  */
    202160
    203 static void summarize(FILE * fp, const char *fmt, char **command,
    204                       resource_t * resp)
    205 {
    206     unsigned long r;    /* Elapsed real milliseconds.  */
    207     unsigned long v;    /* Elapsed virtual (CPU) milliseconds.  */
     161#ifndef TICKS_PER_SEC
     162#define TICKS_PER_SEC 100
     163#endif
     164
     165static void summarize(const char *fmt, char **command, resource_t * resp)
     166{
     167    unsigned vv_ms;     /* Elapsed virtual (CPU) milliseconds */
     168    unsigned cpu_ticks; /* Same, in "CPU ticks" */
    208169
    209170    if (WIFSTOPPED(resp->waitstatus))
    210         fprintf(fp, "Command stopped by signal %d\n",
     171        printf("Command stopped by signal %u\n",
    211172                WSTOPSIG(resp->waitstatus));
    212173    else if (WIFSIGNALED(resp->waitstatus))
    213         fprintf(fp, "Command terminated by signal %d\n",
     174        printf("Command terminated by signal %u\n",
    214175                WTERMSIG(resp->waitstatus));
    215176    else if (WIFEXITED(resp->waitstatus) && WEXITSTATUS(resp->waitstatus))
    216         fprintf(fp, "Command exited with non-zero status %d\n",
     177        printf("Command exited with non-zero status %u\n",
    217178                WEXITSTATUS(resp->waitstatus));
    218179
    219     /* Convert all times to milliseconds.  Occasionally, one of these values
    220        comes out as zero.  Dividing by zero causes problems, so we first
    221        check the time value.  If it is zero, then we take `evasive action'
    222        instead of calculating a value.  */
    223 
    224     r = resp->elapsed.tv_sec * 1000 + resp->elapsed.tv_usec / 1000;
    225 
    226     v = resp->ru.ru_utime.tv_sec * 1000 + resp->ru.ru_utime.TV_MSEC +
    227         resp->ru.ru_stime.tv_sec * 1000 + resp->ru.ru_stime.TV_MSEC;
     180    vv_ms = (resp->ru.ru_utime.tv_sec + resp->ru.ru_stime.tv_sec) * 1000
     181          + (resp->ru.ru_utime.tv_usec + resp->ru.ru_stime.tv_usec) / 1000;
     182
     183#if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000
     184    /* 1000 is exactly divisible by TICKS_PER_SEC */
     185    cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC);
     186#else
     187    cpu_ticks = vv_ms * (unsigned long long)TICKS_PER_SEC / 1000;
     188#endif
     189    if (!cpu_ticks) cpu_ticks = 1; /* we divide by it, must be nonzero */
     190
     191    /* putchar() != putc(stdout) in glibc! */
    228192
    229193    while (*fmt) {
     194        /* Handle leading literal part */
     195        int n = strcspn(fmt, "%\\");
     196        if (n) {
     197            printf("%.*s", n, fmt);
     198            fmt += n;
     199            continue;
     200        }
     201
    230202        switch (*fmt) {
     203#ifdef NOT_NEEDED
     204        /* Handle literal char */
     205        /* Usually we optimize for size, but there is a limit
     206         * for everything. With this we do a lot of 1-byte writes */
     207        default:
     208            putc(*fmt, stdout);
     209            break;
     210#endif
     211
    231212        case '%':
    232213            switch (*++fmt) {
    233             case '%':   /* Literal '%'.  */
    234                 putc('%', fp);
    235                 break;
     214#ifdef NOT_NEEDED_YET
     215        /* Our format strings do not have these */
     216        /* and we do not take format str from user */
     217            default:
     218                putc('%', stdout);
     219                /*FALLTHROUGH*/
     220            case '%':
     221                if (!*fmt) goto ret;
     222                putc(*fmt, stdout);
     223                break;
     224#endif
    236225            case 'C':   /* The command that got timed.  */
    237                 fprintargv(fp, command, " ");
     226                printargv(command, " ");
    238227                break;
    239228            case 'D':   /* Average unshared data size.  */
    240                 fprintf(fp, "%lu",
    241                         MSEC_TO_TICKS(v) == 0 ? 0 :
    242                         ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
    243                         ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
    244                 break;
    245             case 'E':   /* Elapsed real (wall clock) time.  */
    246                 if (resp->elapsed.tv_sec >= 3600)   /* One hour -> h:m:s.  */
    247                     fprintf(fp, "%ldh %ldm %02lds",
    248                             resp->elapsed.tv_sec / 3600,
    249                             (resp->elapsed.tv_sec % 3600) / 60,
    250                             resp->elapsed.tv_sec % 60);
     229                printf("%lu",
     230                        ptok((UL) resp->ru.ru_idrss) / cpu_ticks +
     231                        ptok((UL) resp->ru.ru_isrss) / cpu_ticks);
     232                break;
     233            case 'E': { /* Elapsed real (wall clock) time.  */
     234                unsigned seconds = resp->elapsed_ms / 1000;
     235                if (seconds >= 3600)    /* One hour -> h:m:s.  */
     236                    printf("%uh %um %02us",
     237                            seconds / 3600,
     238                            (seconds % 3600) / 60,
     239                            seconds % 60);
    251240                else
    252                     fprintf(fp, "%ldm %ld.%02lds",  /* -> m:s.  */
    253                             resp->elapsed.tv_sec / 60,
    254                             resp->elapsed.tv_sec % 60,
    255                             resp->elapsed.tv_usec / 10000);
    256                 break;
     241                    printf("%um %u.%02us",  /* -> m:s.  */
     242                            seconds / 60,
     243                            seconds % 60,
     244                            (unsigned)(resp->elapsed_ms / 10) % 100);
     245                break;
     246            }
    257247            case 'F':   /* Major page faults.  */
    258                 fprintf(fp, "%ld", resp->ru.ru_majflt);
     248                printf("%lu", resp->ru.ru_majflt);
    259249                break;
    260250            case 'I':   /* Inputs.  */
    261                 fprintf(fp, "%ld", resp->ru.ru_inblock);
     251                printf("%lu", resp->ru.ru_inblock);
    262252                break;
    263253            case 'K':   /* Average mem usage == data+stack+text.  */
    264                 fprintf(fp, "%lu",
    265                         MSEC_TO_TICKS(v) == 0 ? 0 :
    266                         ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v) +
    267                         ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v) +
    268                         ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
     254                printf("%lu",
     255                        ptok((UL) resp->ru.ru_idrss) / cpu_ticks +
     256                        ptok((UL) resp->ru.ru_isrss) / cpu_ticks +
     257                        ptok((UL) resp->ru.ru_ixrss) / cpu_ticks);
    269258                break;
    270259            case 'M':   /* Maximum resident set size.  */
    271                 fprintf(fp, "%lu", ptok((UL) resp->ru.ru_maxrss));
     260                printf("%lu", ptok((UL) resp->ru.ru_maxrss));
    272261                break;
    273262            case 'O':   /* Outputs.  */
    274                 fprintf(fp, "%ld", resp->ru.ru_oublock);
     263                printf("%lu", resp->ru.ru_oublock);
    275264                break;
    276265            case 'P':   /* Percent of CPU this job got.  */
    277266                /* % cpu is (total cpu time)/(elapsed time).  */
    278                 if (r > 0)
    279                     fprintf(fp, "%lu%%", (v * 100 / r));
     267                if (resp->elapsed_ms > 0)
     268                    printf("%u%%", (unsigned)(vv_ms * 100 / resp->elapsed_ms));
    280269                else
    281                     fprintf(fp, "?%%");
     270                    printf("?%%");
    282271                break;
    283272            case 'R':   /* Minor page faults (reclaims).  */
    284                 fprintf(fp, "%ld", resp->ru.ru_minflt);
     273                printf("%lu", resp->ru.ru_minflt);
    285274                break;
    286275            case 'S':   /* System time.  */
    287                 fprintf(fp, "%ld.%02ld",
    288                         resp->ru.ru_stime.tv_sec,
    289                         resp->ru.ru_stime.TV_MSEC / 10);
     276                printf("%u.%02u",
     277                        (unsigned)resp->ru.ru_stime.tv_sec,
     278                        (unsigned)(resp->ru.ru_stime.tv_usec / 10000));
    290279                break;
    291280            case 'T':   /* System time.  */
    292281                if (resp->ru.ru_stime.tv_sec >= 3600) /* One hour -> h:m:s.  */
    293                     fprintf(fp, "%ldh %ldm %02lds",
    294                             resp->ru.ru_stime.tv_sec / 3600,
    295                             (resp->ru.ru_stime.tv_sec % 3600) / 60,
    296                             resp->ru.ru_stime.tv_sec % 60);
     282                    printf("%uh %um %02us",
     283                            (unsigned)(resp->ru.ru_stime.tv_sec / 3600),
     284                            (unsigned)(resp->ru.ru_stime.tv_sec % 3600) / 60,
     285                            (unsigned)(resp->ru.ru_stime.tv_sec % 60));
    297286                else
    298                     fprintf(fp, "%ldm %ld.%02lds",  /* -> m:s.  */
    299                             resp->ru.ru_stime.tv_sec / 60,
    300                             resp->ru.ru_stime.tv_sec % 60,
    301                             resp->ru.ru_stime.tv_usec / 10000);
     287                    printf("%um %u.%02us",  /* -> m:s.  */
     288                            (unsigned)(resp->ru.ru_stime.tv_sec / 60),
     289                            (unsigned)(resp->ru.ru_stime.tv_sec % 60),
     290                            (unsigned)(resp->ru.ru_stime.tv_usec / 10000));
    302291                break;
    303292            case 'U':   /* User time.  */
    304                 fprintf(fp, "%ld.%02ld",
    305                         resp->ru.ru_utime.tv_sec,
    306                         resp->ru.ru_utime.TV_MSEC / 10);
     293                printf("%u.%02u",
     294                        (unsigned)resp->ru.ru_utime.tv_sec,
     295                        (unsigned)(resp->ru.ru_utime.tv_usec / 10000));
    307296                break;
    308297            case 'u':   /* User time.  */
    309298                if (resp->ru.ru_utime.tv_sec >= 3600) /* One hour -> h:m:s.  */
    310                     fprintf(fp, "%ldh %ldm %02lds",
    311                             resp->ru.ru_utime.tv_sec / 3600,
    312                             (resp->ru.ru_utime.tv_sec % 3600) / 60,
    313                             resp->ru.ru_utime.tv_sec % 60);
     299                    printf("%uh %um %02us",
     300                            (unsigned)(resp->ru.ru_utime.tv_sec / 3600),
     301                            (unsigned)(resp->ru.ru_utime.tv_sec % 3600) / 60,
     302                            (unsigned)(resp->ru.ru_utime.tv_sec % 60));
    314303                else
    315                     fprintf(fp, "%ldm %ld.%02lds",  /* -> m:s.  */
    316                             resp->ru.ru_utime.tv_sec / 60,
    317                             resp->ru.ru_utime.tv_sec % 60,
    318                             resp->ru.ru_utime.tv_usec / 10000);
     304                    printf("%um %u.%02us",  /* -> m:s.  */
     305                            (unsigned)(resp->ru.ru_utime.tv_sec / 60),
     306                            (unsigned)(resp->ru.ru_utime.tv_sec % 60),
     307                            (unsigned)(resp->ru.ru_utime.tv_usec / 10000));
    319308                break;
    320309            case 'W':   /* Times swapped out.  */
    321                 fprintf(fp, "%ld", resp->ru.ru_nswap);
     310                printf("%lu", resp->ru.ru_nswap);
    322311                break;
    323312            case 'X':   /* Average shared text size.  */
    324                 fprintf(fp, "%lu",
    325                         MSEC_TO_TICKS(v) == 0 ? 0 :
    326                         ptok((UL) resp->ru.ru_ixrss) / MSEC_TO_TICKS(v));
     313                printf("%lu", ptok((UL) resp->ru.ru_ixrss) / cpu_ticks);
    327314                break;
    328315            case 'Z':   /* Page size.  */
    329                 fprintf(fp, "%d", getpagesize());
     316                printf("%u", getpagesize());
    330317                break;
    331318            case 'c':   /* Involuntary context switches.  */
    332                 fprintf(fp, "%ld", resp->ru.ru_nivcsw);
     319                printf("%lu", resp->ru.ru_nivcsw);
    333320                break;
    334321            case 'e':   /* Elapsed real time in seconds.  */
    335                 fprintf(fp, "%ld.%02ld",
    336                         resp->elapsed.tv_sec, resp->elapsed.tv_usec / 10000);
     322                printf("%u.%02u",
     323                        (unsigned)resp->elapsed_ms / 1000,
     324                        (unsigned)(resp->elapsed_ms / 10) % 100);
    337325                break;
    338326            case 'k':   /* Signals delivered.  */
    339                 fprintf(fp, "%ld", resp->ru.ru_nsignals);
     327                printf("%lu", resp->ru.ru_nsignals);
    340328                break;
    341329            case 'p':   /* Average stack segment.  */
    342                 fprintf(fp, "%lu",
    343                         MSEC_TO_TICKS(v) == 0 ? 0 :
    344                         ptok((UL) resp->ru.ru_isrss) / MSEC_TO_TICKS(v));
     330                printf("%lu", ptok((UL) resp->ru.ru_isrss) / cpu_ticks);
    345331                break;
    346332            case 'r':   /* Incoming socket messages received.  */
    347                 fprintf(fp, "%ld", resp->ru.ru_msgrcv);
     333                printf("%lu", resp->ru.ru_msgrcv);
    348334                break;
    349335            case 's':   /* Outgoing socket messages sent.  */
    350                 fprintf(fp, "%ld", resp->ru.ru_msgsnd);
     336                printf("%lu", resp->ru.ru_msgsnd);
    351337                break;
    352338            case 't':   /* Average resident set size.  */
    353                 fprintf(fp, "%lu",
    354                         MSEC_TO_TICKS(v) == 0 ? 0 :
    355                         ptok((UL) resp->ru.ru_idrss) / MSEC_TO_TICKS(v));
     339                printf("%lu", ptok((UL) resp->ru.ru_idrss) / cpu_ticks);
    356340                break;
    357341            case 'w':   /* Voluntary context switches.  */
    358                 fprintf(fp, "%ld", resp->ru.ru_nvcsw);
     342                printf("%lu", resp->ru.ru_nvcsw);
    359343                break;
    360344            case 'x':   /* Exit status.  */
    361                 fprintf(fp, "%d", WEXITSTATUS(resp->waitstatus));
    362                 break;
    363             case '\0':
    364                 putc('?', fp);
    365                 return;
    366             default:
    367                 putc('?', fp);
    368                 putc(*fmt, fp);
     345                printf("%u", WEXITSTATUS(resp->waitstatus));
     346                break;
    369347            }
    370             ++fmt;
    371348            break;
    372349
     350#ifdef NOT_NEEDED_YET
    373351        case '\\':      /* Format escape.  */
    374352            switch (*++fmt) {
     353            default:
     354                putc('\\', stdout);
     355                /*FALLTHROUGH*/
     356            case '\\':
     357                if (!*fmt) goto ret;
     358                putc(*fmt, stdout);
     359                break;
    375360            case 't':
    376                 putc('\t', fp);
     361                putc('\t', stdout);
    377362                break;
    378363            case 'n':
    379                 putc('\n', fp);
    380                 break;
    381             case '\\':
    382                 putc('\\', fp);
    383                 break;
    384             default:
    385                 putc('?', fp);
    386                 putc('\\', fp);
    387                 putc(*fmt, fp);
     364                putc('\n', stdout);
     365                break;
    388366            }
    389             ++fmt;
    390367            break;
    391 
    392         default:
    393             putc(*fmt++, fp);
     368#endif
    394369        }
    395 
    396         if (ferror(fp))
    397             bb_error_msg_and_die(bb_msg_write_error);
    398     }
    399     putc('\n', fp);
    400 
    401     if (ferror(fp))
    402         bb_error_msg_and_die(bb_msg_write_error);
     370        ++fmt;
     371    }
     372 /* ret: */
     373    putc('\n', stdout);
    403374}
    404375
     
    410381    __sighandler_t interrupt_signal, quit_signal;
    411382
    412     gettimeofday(&resp->start, (struct timezone *) 0);
     383    resp->elapsed_ms = monotonic_us() / 1000;
    413384    pid = vfork();      /* Run CMD as child process.  */
    414385    if (pid < 0)
     
    417388        /* Don't cast execvp arguments; that causes errors on some systems,
    418389           versus merely warnings if the cast is left off.  */
    419         execvp(cmd[0], cmd);
     390        BB_EXECVP(cmd[0], cmd);
    420391        bb_error_msg("cannot run %s", cmd[0]);
    421392        _exit(errno == ENOENT ? 127 : 126);
     
    434405}
    435406
     407int time_main(int argc, char **argv);
    436408int time_main(int argc, char **argv)
    437409{
    438     int gotone;
    439410    resource_t res;
    440411    const char *output_format = default_format;
    441 
    442     argc--;
    443     argv++;
     412    char c;
     413
     414    goto next;
    444415    /* Parse any options  -- don't use getopt() here so we don't
    445416     * consume the args of our client application... */
    446     while (argc > 0 && **argv == '-') {
    447         gotone = 0;
    448         while (gotone == 0 && *++(*argv)) {
    449             switch (**argv) {
     417    while (argc > 0 && argv[0][0] == '-') {
     418        while ((c = *++*argv)) {
     419            switch (c) {
    450420            case 'v':
    451421                output_format = long_format;
     
    457427                bb_show_usage();
    458428            }
    459             argc--;
    460             argv++;
    461             gotone = 1;
    462429        }
    463     }
    464 
    465     if (argv == NULL || *argv == NULL)
    466         bb_show_usage();
     430 next:
     431        argv++;
     432        argc--;
     433        if (!argc)
     434            bb_show_usage();
     435    }
    467436
    468437    run_command(argv, &res);
    469     summarize(stderr, output_format, argv, &res);
    470     fflush(stderr);
     438
     439    /* Cheat. printf's are shorter :) */
     440    stdout = stderr;
     441    dup2(2, 1); /* just in case libc does something silly :( */
     442    summarize(output_format, argv, &res);
    471443
    472444    if (WIFSTOPPED(res.waitstatus))
    473         exit(WSTOPSIG(res.waitstatus));
    474     else if (WIFSIGNALED(res.waitstatus))
    475         exit(WTERMSIG(res.waitstatus));
    476     else if (WIFEXITED(res.waitstatus))
    477         exit(WEXITSTATUS(res.waitstatus));
    478     return 0;
    479 }
     445        return WSTOPSIG(res.waitstatus);
     446    if (WIFSIGNALED(res.waitstatus))
     447        return WTERMSIG(res.waitstatus);
     448    if (WIFEXITED(res.waitstatus))
     449        return WEXITSTATUS(res.waitstatus);
     450    fflush_stdout_and_exit(0);
     451}
Note: See TracChangeset for help on using the changeset viewer.