Ignore:
Timestamp:
Feb 25, 2011, 9:26:54 PM (13 years ago)
Author:
Bruno Cornec
Message:
  • Update mindi-busybox to 1.18.3 to avoid problems with the tar command which is now failing on recent versions with busybox 1.7.3
File:
1 edited

Legend:

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

    r1765 r2725  
    11/* vi: set sw=4 ts=4: */
    2 /* `time' utility to display resource usage of processes.
     2/* 'time' utility to display resource usage of processes.
    33   Copyright (C) 1990, 91, 92, 93, 96 Free Software Foundation, Inc.
    44
    5    Licensed under GPL version 2, see file LICENSE in this tarball for details.
     5   Licensed under GPLv2, see file LICENSE in this source tree.
    66*/
    77/* Originally written by David Keppel <pardo@cs.washington.edu>.
     
    2828/* The output format for the -p option .*/
    2929static const char posix_format[] ALIGN1 = "real %e\nuser %U\nsys %S";
    30 
    3130
    3231/* Format string for printing all statistics verbosely.
     
    5756    "\tExit status: %x";
    5857
    59 
    6058/* Wait for and fill in data on child process PID.
    6159   Return 0 on error, 1 if ok.  */
    62 
    6360/* pid_t is short on BSDI, so don't try to promote it.  */
    64 static int resuse_end(pid_t pid, resource_t * resp)
    65 {
    66     int status;
     61static void resuse_end(pid_t pid, resource_t *resp)
     62{
    6763    pid_t caught;
    6864
    6965    /* Ignore signals, but don't ignore the children.  When wait3
    7066       returns the child process, set the time the command finished. */
    71     while ((caught = wait3(&status, 0, &resp->ru)) != pid) {
    72         if (caught == -1)
    73             return 0;
     67    while ((caught = wait3(&resp->waitstatus, 0, &resp->ru)) != pid) {
     68        if (caught == -1 && errno != EINTR) {
     69            bb_perror_msg("wait");
     70            return;
     71        }
    7472    }
    75     resp->elapsed_ms = (monotonic_us() / 1000) - resp->elapsed_ms;
    76     resp->waitstatus = status;
    77     return 1;
    78 }
    79 
    80 /* Print ARGV, with each entry in ARGV separated by FILLER.  */
    81 static 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     }
     73    resp->elapsed_ms = monotonic_ms() - resp->elapsed_ms;
     74}
     75
     76static void printargv(char *const *argv)
     77{
     78    const char *fmt = " %s" + 1;
     79    do {
     80        printf(fmt, *argv);
     81        fmt = " %s";
     82    } while (*++argv);
    8883}
    8984
     
    9590   Note: Some machines express getrusage statistics in terms of K,
    9691   others in terms of pages.  */
    97 
    98 static unsigned long ptok(unsigned long pages)
    99 {
    100     static unsigned long ps;
     92static unsigned long ptok(const unsigned pagesize, const unsigned long pages)
     93{
    10194    unsigned long tmp;
    10295
    103     /* Initialization.  */
    104     if (ps == 0)
    105         ps = getpagesize();
    106 
    10796    /* Conversion.  */
    108     if (pages > (LONG_MAX / ps)) {  /* Could overflow.  */
    109         tmp = pages / 1024; /* Smaller first, */
    110         return tmp * ps;    /* then larger.  */
     97    if (pages > (LONG_MAX / pagesize)) { /* Could overflow.  */
     98        tmp = pages / 1024;     /* Smaller first, */
     99        return tmp * pagesize;  /* then larger.  */
    111100    }
    112101    /* Could underflow.  */
    113     tmp = pages * ps;   /* Larger first, */
    114     return tmp / 1024;  /* then smaller.  */
     102    tmp = pages * pagesize; /* Larger first, */
     103    return tmp / 1024;      /* then smaller.  */
    115104}
    116105
     
    163152#endif
    164153
    165 static void summarize(const char *fmt, char **command, resource_t * resp)
     154static void summarize(const char *fmt, char **command, resource_t *resp)
    166155{
    167156    unsigned vv_ms;     /* Elapsed virtual (CPU) milliseconds */
    168157    unsigned cpu_ticks; /* Same, in "CPU ticks" */
    169 
     158    unsigned pagesize = getpagesize();
     159
     160    /* Impossible: we do not use WUNTRACED flag in wait()...
    170161    if (WIFSTOPPED(resp->waitstatus))
    171162        printf("Command stopped by signal %u\n",
    172163                WSTOPSIG(resp->waitstatus));
    173     else if (WIFSIGNALED(resp->waitstatus))
     164    else */
     165    if (WIFSIGNALED(resp->waitstatus))
    174166        printf("Command terminated by signal %u\n",
    175167                WTERMSIG(resp->waitstatus));
     
    182174
    183175#if (1000 / TICKS_PER_SEC) * TICKS_PER_SEC == 1000
    184     /* 1000 is exactly divisible by TICKS_PER_SEC */
     176    /* 1000 is exactly divisible by TICKS_PER_SEC (typical) */
    185177    cpu_ticks = vv_ms / (1000 / TICKS_PER_SEC);
    186178#else
     
    188180#endif
    189181    if (!cpu_ticks) cpu_ticks = 1; /* we divide by it, must be nonzero */
    190 
    191     /* putchar() != putc(stdout) in glibc! */
    192182
    193183    while (*fmt) {
     
    206196         * for everything. With this we do a lot of 1-byte writes */
    207197        default:
    208             putc(*fmt, stdout);
     198            bb_putchar(*fmt);
    209199            break;
    210200#endif
     
    216206        /* and we do not take format str from user */
    217207            default:
    218                 putc('%', stdout);
     208                bb_putchar('%');
    219209                /*FALLTHROUGH*/
    220210            case '%':
    221211                if (!*fmt) goto ret;
    222                 putc(*fmt, stdout);
     212                bb_putchar(*fmt);
    223213                break;
    224214#endif
    225215            case 'C':   /* The command that got timed.  */
    226                 printargv(command, " ");
     216                printargv(command);
    227217                break;
    228218            case 'D':   /* Average unshared data size.  */
    229219                printf("%lu",
    230                         ptok((UL) resp->ru.ru_idrss) / cpu_ticks +
    231                         ptok((UL) resp->ru.ru_isrss) / cpu_ticks);
     220                    (ptok(pagesize, (UL) resp->ru.ru_idrss) +
     221                     ptok(pagesize, (UL) resp->ru.ru_isrss)) / cpu_ticks);
    232222                break;
    233223            case 'E': { /* Elapsed real (wall clock) time.  */
     
    253243            case 'K':   /* Average mem usage == data+stack+text.  */
    254244                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);
     245                    (ptok(pagesize, (UL) resp->ru.ru_idrss) +
     246                     ptok(pagesize, (UL) resp->ru.ru_isrss) +
     247                     ptok(pagesize, (UL) resp->ru.ru_ixrss)) / cpu_ticks);
    258248                break;
    259249            case 'M':   /* Maximum resident set size.  */
    260                 printf("%lu", ptok((UL) resp->ru.ru_maxrss));
     250                printf("%lu", ptok(pagesize, (UL) resp->ru.ru_maxrss));
    261251                break;
    262252            case 'O':   /* Outputs.  */
     
    311301                break;
    312302            case 'X':   /* Average shared text size.  */
    313                 printf("%lu", ptok((UL) resp->ru.ru_ixrss) / cpu_ticks);
     303                printf("%lu", ptok(pagesize, (UL) resp->ru.ru_ixrss) / cpu_ticks);
    314304                break;
    315305            case 'Z':   /* Page size.  */
    316                 printf("%u", getpagesize());
     306                printf("%u", pagesize);
    317307                break;
    318308            case 'c':   /* Involuntary context switches.  */
     
    328318                break;
    329319            case 'p':   /* Average stack segment.  */
    330                 printf("%lu", ptok((UL) resp->ru.ru_isrss) / cpu_ticks);
     320                printf("%lu", ptok(pagesize, (UL) resp->ru.ru_isrss) / cpu_ticks);
    331321                break;
    332322            case 'r':   /* Incoming socket messages received.  */
     
    337327                break;
    338328            case 't':   /* Average resident set size.  */
    339                 printf("%lu", ptok((UL) resp->ru.ru_idrss) / cpu_ticks);
     329                printf("%lu", ptok(pagesize, (UL) resp->ru.ru_idrss) / cpu_ticks);
    340330                break;
    341331            case 'w':   /* Voluntary context switches.  */
     
    352342            switch (*++fmt) {
    353343            default:
    354                 putc('\\', stdout);
     344                bb_putchar('\\');
    355345                /*FALLTHROUGH*/
    356346            case '\\':
    357347                if (!*fmt) goto ret;
    358                 putc(*fmt, stdout);
     348                bb_putchar(*fmt);
    359349                break;
    360350            case 't':
    361                 putc('\t', stdout);
     351                bb_putchar('\t');
    362352                break;
    363353            case 'n':
    364                 putc('\n', stdout);
     354                bb_putchar('\n');
    365355                break;
    366356            }
     
    371361    }
    372362 /* ret: */
    373     putc('\n', stdout);
     363    bb_putchar('\n');
    374364}
    375365
    376366/* Run command CMD and return statistics on it.
    377367   Put the statistics in *RESP.  */
    378 static void run_command(char *const *cmd, resource_t * resp)
    379 {
    380     pid_t pid;          /* Pid of child.  */
    381     __sighandler_t interrupt_signal, quit_signal;
    382 
    383     resp->elapsed_ms = monotonic_us() / 1000;
    384     pid = vfork();      /* Run CMD as child process.  */
    385     if (pid < 0)
    386         bb_error_msg_and_die("cannot fork");
    387     else if (pid == 0) {    /* If child.  */
    388         /* Don't cast execvp arguments; that causes errors on some systems,
    389            versus merely warnings if the cast is left off.  */
    390         BB_EXECVP(cmd[0], cmd);
    391         bb_error_msg("cannot run %s", cmd[0]);
    392         _exit(errno == ENOENT ? 127 : 126);
     368static void run_command(char *const *cmd, resource_t *resp)
     369{
     370    pid_t pid;
     371    void (*interrupt_signal)(int);
     372    void (*quit_signal)(int);
     373
     374    resp->elapsed_ms = monotonic_ms();
     375    pid = xvfork();
     376    if (pid == 0) {
     377        /* Child */
     378        BB_EXECVP_or_die((char**)cmd);
    393379    }
    394380
    395381    /* Have signals kill the child but not self (if possible).  */
     382//TODO: just block all sigs? and reenable them in the very end in main?
    396383    interrupt_signal = signal(SIGINT, SIG_IGN);
    397384    quit_signal = signal(SIGQUIT, SIG_IGN);
    398385
    399     if (resuse_end(pid, resp) == 0)
    400         bb_error_msg("error waiting for child process");
     386    resuse_end(pid, resp);
    401387
    402388    /* Re-enable signals.  */
     
    405391}
    406392
    407 int time_main(int argc, char **argv);
    408 int time_main(int argc, char **argv)
     393int time_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
     394int time_main(int argc UNUSED_PARAM, char **argv)
    409395{
    410396    resource_t res;
    411397    const char *output_format = default_format;
    412     char c;
    413 
    414     goto next;
    415     /* Parse any options  -- don't use getopt() here so we don't
    416      * consume the args of our client application... */
    417     while (argc > 0 && argv[0][0] == '-') {
    418         while ((c = *++*argv)) {
    419             switch (c) {
    420             case 'v':
    421                 output_format = long_format;
    422                 break;
    423             case 'p':
    424                 output_format = posix_format;
    425                 break;
    426             default:
    427                 bb_show_usage();
    428             }
    429         }
    430  next:
    431         argv++;
    432         argc--;
    433         if (!argc)
    434             bb_show_usage();
    435     }
     398    int opt;
     399
     400    opt_complementary = "-1"; /* at least one arg */
     401    /* "+": stop on first non-option */
     402    opt = getopt32(argv, "+vp");
     403    argv += optind;
     404    if (opt & 1)
     405        output_format = long_format;
     406    if (opt & 2)
     407        output_format = posix_format;
    436408
    437409    run_command(argv, &res);
    438410
    439411    /* Cheat. printf's are shorter :) */
    440     stdout = stderr;
    441     dup2(2, 1); /* just in case libc does something silly :( */
     412    xdup2(STDERR_FILENO, STDOUT_FILENO);
    442413    summarize(output_format, argv, &res);
    443414
     
    448419    if (WIFEXITED(res.waitstatus))
    449420        return WEXITSTATUS(res.waitstatus);
    450     fflush_stdout_and_exit(0);
    451 }
     421    fflush_stdout_and_exit(EXIT_SUCCESS);
     422}
Note: See TracChangeset for help on using the changeset viewer.