#include <locale.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <stdio.h>
#include <err.h>
#include <errno.h>
#include <math.h>
#include <limits.h>
#include <time.h>
#include <libintl.h>
typedef struct {
char sm_char;
uint64_t sm_adj;
} sleep_map_t;
static const sleep_map_t sleep_map[] = {
{ 's', 1 },
{ 'm', 60 },
{ 'h', 60 * 60 },
{ 'd', 60 * 60 * 24 },
{ 'w', 60 * 60 * 24 * 7 },
{ 'y', 60 * 60 * 24 * 365 },
{ '\0', 0 }
};
static void
sleep_sigalrm(int sig)
{
_exit(0);
}
int
main(int argc, char *argv[])
{
int c;
long double d, sec, frac;
char *eptr;
(void) setlocale(LC_ALL, "");
#if !defined(TEXT_DOMAIN)
#define TEXT_DOMAIN "SYS_TEST"
#endif
(void) textdomain(TEXT_DOMAIN);
(void) signal(SIGALRM, sleep_sigalrm);
while ((c = getopt(argc, argv, ":")) != -1) {
switch (c) {
case '?':
warnx(gettext("illegal option -- %c"), optopt);
(void) fprintf(stderr,
gettext("Usage: sleep time[suffix]\n"));
exit(EXIT_FAILURE);
}
}
argc -= optind;
argv += optind;
if (argc != 1) {
warnx(gettext("only one operand is supported"));
(void) fprintf(stderr, gettext("Usage: sleep time[suffix]\n"));
exit(EXIT_FAILURE);
}
errno = 0;
d = strtold(argv[0], &eptr);
if (errno != 0 || (eptr[0] != '\0' && eptr[1] != '\0') ||
eptr == argv[0] || d == NAN) {
errx(EXIT_FAILURE, gettext("failed to parse time '%s'"),
argv[0]);
}
if (d < 0.0) {
errx(EXIT_FAILURE,
gettext("time interval '%s', cannot be negative"), argv[0]);
}
if (eptr[0] != '\0') {
int i;
for (i = 0; sleep_map[i].sm_char != '\0'; i++) {
if (sleep_map[i].sm_char == eptr[0]) {
d *= sleep_map[i].sm_adj;
break;
}
}
if (sleep_map[i].sm_char == '\0') {
errx(EXIT_FAILURE, gettext("failed to parse time %s"),
argv[0]);
}
}
if (d == 0) {
exit(EXIT_SUCCESS);
}
frac = modfl(d, &sec);
while (sec > 0 || frac != 0) {
struct timespec ts;
if (frac != 0) {
frac *= NANOSEC;
ts.tv_nsec = (long)frac;
frac = 0;
} else {
ts.tv_nsec = 0;
}
if (sec > (float)INT_MAX) {
ts.tv_sec = INT_MAX;
} else {
ts.tv_sec = (time_t)sec;
}
sec -= ts.tv_sec;
if (nanosleep(&ts, NULL) != 0) {
err(EXIT_FAILURE, gettext("nanosleep failed"));
}
}
return (0);
}