busybox/coreutils/sleep.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * sleep implementation for busybox
   4 *
   5 * Copyright (C) 2003  Manuel Novoa III  <mjn3@codepoet.org>
   6 *
   7 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
   8 */
   9
  10/* BB_AUDIT SUSv3 compliant */
  11/* BB_AUDIT GNU issues -- fancy version matches except args must be ints. */
  12/* http://www.opengroup.org/onlinepubs/007904975/utilities/sleep.html */
  13
  14/* Mar 16, 2003      Manuel Novoa III   (mjn3@codepoet.org)
  15 *
  16 * Rewritten to do proper arg and error checking.
  17 * Also, added a 'fancy' configuration to accept multiple args with
  18 * time suffixes for seconds, minutes, hours, and days.
  19 */
  20
  21//usage:#define sleep_trivial_usage
  22//usage:        IF_FEATURE_FANCY_SLEEP("[") "N" IF_FEATURE_FANCY_SLEEP("]...")
  23//usage:#define sleep_full_usage "\n\n"
  24//usage:        IF_NOT_FEATURE_FANCY_SLEEP("Pause for N seconds")
  25//usage:        IF_FEATURE_FANCY_SLEEP(
  26//usage:       "Pause for a time equal to the total of the args given, where each arg can\n"
  27//usage:       "have an optional suffix of (s)econds, (m)inutes, (h)ours, or (d)ays")
  28//usage:
  29//usage:#define sleep_example_usage
  30//usage:       "$ sleep 2\n"
  31//usage:       "[2 second delay results]\n"
  32//usage:        IF_FEATURE_FANCY_SLEEP(
  33//usage:       "$ sleep 1d 3h 22m 8s\n"
  34//usage:       "[98528 second delay results]\n")
  35
  36#include "libbb.h"
  37
  38/* Do not make this applet NOFORK. It breaks ^C-ing of pauses in shells */
  39
  40
  41#if ENABLE_FEATURE_FANCY_SLEEP || ENABLE_FEATURE_FLOAT_SLEEP
  42static const struct suffix_mult sfx[] = {
  43        { "s", 1 },
  44        { "m", 60 },
  45        { "h", 60*60 },
  46        { "d", 24*60*60 },
  47        { "", 0 }
  48};
  49#endif
  50
  51int sleep_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
  52int sleep_main(int argc UNUSED_PARAM, char **argv)
  53{
  54#if ENABLE_FEATURE_FLOAT_SLEEP
  55        double duration;
  56        struct timespec ts;
  57#else
  58        unsigned duration;
  59#endif
  60
  61        ++argv;
  62        if (!*argv)
  63                bb_show_usage();
  64
  65#if ENABLE_FEATURE_FLOAT_SLEEP
  66
  67# if ENABLE_LOCALE_SUPPORT
  68        /* undo busybox.c setlocale */
  69        setlocale(LC_NUMERIC, "C");
  70# endif
  71        duration = 0;
  72        do {
  73                char *arg = *argv;
  74                if (strchr(arg, '.')) {
  75                        double d;
  76                        char *pp;
  77                        int len = strspn(arg, "0123456789.");
  78                        char sv = arg[len];
  79                        arg[len] = '\0';
  80                        errno = 0;
  81                        d = strtod(arg, &pp);
  82                        if (errno || *pp)
  83                                bb_show_usage();
  84                        arg += len;
  85                        *arg-- = sv;
  86                        sv = *arg;
  87                        *arg = '1';
  88                        duration += d * xatoul_sfx(arg, sfx);
  89                        *arg = sv;
  90                } else {
  91                        duration += xatoul_sfx(arg, sfx);
  92                }
  93        } while (*++argv);
  94
  95        ts.tv_sec = MAXINT(typeof(ts.tv_sec));
  96        ts.tv_nsec = 0;
  97        if (duration >= 0 && duration < ts.tv_sec) {
  98                ts.tv_sec = duration;
  99                ts.tv_nsec = (duration - ts.tv_sec) * 1000000000;
 100        }
 101        do {
 102                errno = 0;
 103                nanosleep(&ts, &ts);
 104        } while (errno == EINTR);
 105
 106#elif ENABLE_FEATURE_FANCY_SLEEP
 107
 108        duration = 0;
 109        do {
 110                duration += xatou_range_sfx(*argv, 0, UINT_MAX - duration, sfx);
 111        } while (*++argv);
 112        sleep(duration);
 113
 114#else /* simple */
 115
 116        duration = xatou(*argv);
 117        sleep(duration);
 118        // Off. If it's really needed, provide example why
 119        //if (sleep(duration)) {
 120        //      bb_perror_nomsg_and_die();
 121        //}
 122
 123#endif
 124
 125        return EXIT_SUCCESS;
 126}
 127