diff options
author | Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> | 2019-02-01 22:55:37 +0000 |
---|---|---|
committer | Kiyoshi Aman <kiyoshi.aman+adelie@gmail.com> | 2019-02-03 18:22:05 -0600 |
commit | 5b57d28ffb6e1ef86b50f7d05d977826eae89bfe (patch) | |
tree | 154a22fe556b49e6927197336f8bf91b12eacd5e /bin/sleep | |
download | userland-5b57d28ffb6e1ef86b50f7d05d977826eae89bfe.tar.gz userland-5b57d28ffb6e1ef86b50f7d05d977826eae89bfe.tar.bz2 userland-5b57d28ffb6e1ef86b50f7d05d977826eae89bfe.tar.xz userland-5b57d28ffb6e1ef86b50f7d05d977826eae89bfe.zip |
initial population
Diffstat (limited to 'bin/sleep')
-rw-r--r-- | bin/sleep/sleep.1 | 177 | ||||
-rw-r--r-- | bin/sleep/sleep.c | 229 |
2 files changed, 406 insertions, 0 deletions
diff --git a/bin/sleep/sleep.1 b/bin/sleep/sleep.1 new file mode 100644 index 0000000..1ee73b3 --- /dev/null +++ b/bin/sleep/sleep.1 @@ -0,0 +1,177 @@ +.\" $NetBSD: sleep.1,v 1.27 2019/01/27 17:42:53 wiz Exp $ +.\" +.\" Copyright (c) 1990, 1993, 1994 +.\" The Regents of the University of California. All rights reserved. +.\" +.\" This code is derived from software contributed to Berkeley by +.\" the Institute of Electrical and Electronics Engineers, Inc. +.\" +.\" Redistribution and use in source and binary forms, with or without +.\" modification, are permitted provided that the following conditions +.\" are met: +.\" 1. Redistributions of source code must retain the above copyright +.\" notice, this list of conditions and the following disclaimer. +.\" 2. Redistributions in binary form must reproduce the above copyright +.\" notice, this list of conditions and the following disclaimer in the +.\" documentation and/or other materials provided with the distribution. +.\" 3. Neither the name of the University nor the names of its contributors +.\" may be used to endorse or promote products derived from this software +.\" without specific prior written permission. +.\" +.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND +.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE +.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +.\" SUCH DAMAGE. +.\" +.\" @(#)sleep.1 8.3 (Berkeley) 4/18/94 +.\" +.Dd January 26, 2019 +.Dt SLEEP 1 +.Os +.Sh NAME +.Nm sleep +.Nd suspend execution for an interval of time +.Sh SYNOPSIS +.Nm +.Ar seconds +.Sh DESCRIPTION +The +.Nm +utility suspends execution for a minimum of +.Ar seconds +seconds, then exits. +It is usually used to schedule the execution of other commands (see +.Sx EXAMPLES +below). +.Pp +Note: The +.Nx +.Nm +command will accept and honor a non-integer number of specified seconds. +Note however, that if the request is for much more than 2.5 hours, +any fractional seconds will be ignored. +Permitting non-integral delays is a non-portable extension, +and its use will decrease the probability that +a shell script will execute properly on another system. +.Pp +When the +.Dv SIGINFO +signal is received, an estimate of the number of seconds remaining to +sleep is printed on the standard output. +.Sh EXIT STATUS +The +.Nm +utility exits with one of the following values: +.Bl -tag -width flag +.It Li \&0 +On successful completion, or if the signal +.Dv SIGALRM +was received. +.It Li \&>\&0 +An error occurred. +.El +.Sh EXAMPLES +To schedule the execution of a command for 1800 seconds later: +.Pp +.Dl (sleep 1800; sh command_file >errors 2>&1)& +.Pp +This incantation would wait half an hour before +running the script +.Dq command_file . +(See the +.Xr at 1 +utility.) +.Pp +To repeatedly run a command (using +.Xr csh 1 ) : +.Pp +.Bd -literal -offset indent -compact +while (1) + if (! -r zzz.rawdata) then + sleep 300 + else + foreach i (*.rawdata) + sleep 70 + awk -f collapse_data $i >> results + end + break + endif +end +.Ed +.Pp +The scenario for a script such as this might be: a program currently +running is taking longer than expected to process a series of +files, and it would be nice to have +another program start processing the files created by the first +program as soon as it is finished (when zzz.rawdata is created). +The script checks every five minutes for the file zzz.rawdata. +When the file is found, processing the generated files (*.rawdata) +is done courteously by sleeping for 70 seconds in between each +awk job. +.Pp +To wait until a particular time, the following, +with some error checking added, might be used (using +.Xr sh 1 +on +.Nx ) : +.Bd -literal -offset indent +END=$(( $( date -d "$1" +%s ) - START_TIME )) +while [ "${SECONDS}" -lt "${END}" ] +do + sleep "$((END - SECONDS))" +done +.Ed +.Pp +where the argument +.Sq \&$1 +specifies the desired date and time in any format the +.Fl d +option to the +.Xr date 1 +command accepts. +.Sh SEE ALSO +.Xr at 1 , +.Xr csh 1 , +.Xr date 1 , +.Xr sh 1 , +.Xr nanosleep 2 , +.Xr sleep 3 +.Sh STANDARDS +The +.Nm +command is expected to be +.St -p1003.2 +compatible. +.Sh HISTORY +A +.Nm +utility appeared in +.At v4 . +Processing fractional seconds, and processing the +.Ic seconds +argument respecting the current locale, was added in +.Nx 1.3 . +The ability to sleep for extended periods appeared in +.Nx 9 . +.Sh BUGS +This +.Nm +command cannot handle requests for durations +much longer than about 250 billion years. +Any such attempt will result in an error, +and immediate termination. +It is suggested that when there is a need +for sleeps exceeding this period, the +.Nm +command be executed in a loop, with each +individual +.Nm +invocation limited to 200 billion years +approximately. diff --git a/bin/sleep/sleep.c b/bin/sleep/sleep.c new file mode 100644 index 0000000..dfaf302 --- /dev/null +++ b/bin/sleep/sleep.c @@ -0,0 +1,229 @@ +/* $NetBSD: sleep.c,v 1.29 2019/01/27 02:00:45 christos Exp $ */ + +/* + * Copyright (c) 1988, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include <sys/cdefs.h> +#ifndef lint +__COPYRIGHT("@(#) Copyright (c) 1988, 1993, 1994\ + The Regents of the University of California. All rights reserved."); +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)sleep.c 8.3 (Berkeley) 4/2/94"; +#else +__RCSID("$NetBSD: sleep.c,v 1.29 2019/01/27 02:00:45 christos Exp $"); +#endif +#endif /* not lint */ + +#include <ctype.h> +#include <err.h> +#include <locale.h> +#include <math.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <time.h> +#include <unistd.h> + +__dead static void alarmhandle(int); +__dead static void usage(void); + +static void report(const time_t, const time_t, const char *const); + +static volatile sig_atomic_t report_requested; +static void +report_request(int signo __unused) +{ + + report_requested = 1; +} + +int +main(int argc, char *argv[]) +{ + char *arg, *temp; + const char *msg; + double fval, ival, val; + struct timespec ntime; + time_t original; + int ch, fracflag; + unsigned delay; + + setprogname(argv[0]); + (void)setlocale(LC_ALL, ""); + + (void)signal(SIGALRM, alarmhandle); + + while ((ch = getopt(argc, argv, "")) != -1) + switch(ch) { + default: + usage(); + } + argc -= optind; + argv += optind; + + if (argc != 1) + usage(); + + /* + * Okay, why not just use atof for everything? Why bother + * checking if there is a fraction in use? Because the old + * sleep handled the full range of integers, that's why, and a + * double can't handle a large long. This is fairly useless + * given how large a number a double can hold on most + * machines, but now we won't ever have trouble. If you want + * 1000000000.9 seconds of sleep, well, that's your + * problem. Why use an isdigit() check instead of checking for + * a period? Because doing it this way means locales will be + * handled transparently by the atof code. + * + * Since fracflag is set for any non-digit, we also fall + * into the floating point conversion path if the input + * is hex (the 'x' in 0xA is not a digit). Then if + * strtod() handles hex (on NetBSD it does) so will we. + * That path is also taken for scientific notation (1.2e+3) + * and when the input is simply nonsense. + */ + fracflag = 0; + arg = *argv; + for (temp = arg; *temp != '\0'; temp++) + if (!isdigit((unsigned char)*temp)) { + ch = *temp; + fracflag++; + } + + if (fracflag) { + /* + * If we cannot convert the value using the user's locale + * then try again using the C locale, so strtod() can always + * parse values like 2.5, even if the user's locale uses + * a different decimal radix character (like ',') + * + * (but only if that is the potential problem) + */ + val = strtod(arg, &temp); + if (*temp != '\0') + val = strtod_l(arg, &temp, LC_C_LOCALE); + if (val < 0 || temp == arg || *temp != '\0') + usage(); + + ival = floor(val); + fval = (1000000000 * (val-ival)); + ntime.tv_sec = ival; + if ((double)ntime.tv_sec != ival) + errx(1, "requested delay (%s) out of range", arg); + ntime.tv_nsec = fval; + + if (ntime.tv_sec == 0 && ntime.tv_nsec == 0) + return EXIT_SUCCESS; /* was 0.0 or underflowed */ + } else { + ntime.tv_sec = strtol(arg, &temp, 10); + if (ntime.tv_sec < 0 || temp == arg || *temp != '\0') + usage(); + + if (ntime.tv_sec == 0) + return EXIT_SUCCESS; + ntime.tv_nsec = 0; + } + + original = ntime.tv_sec; + if (ntime.tv_nsec != 0) + msg = " and a bit"; + else + msg = ""; + + signal(SIGINFO, report_request); + + if (ntime.tv_sec <= 10000) { /* arbitrary */ + while (nanosleep(&ntime, &ntime) != 0) { + if (report_requested) { + report(ntime.tv_sec, original, msg); + report_requested = 0; + } else + err(EXIT_FAILURE, "nanosleep failed"); + } + } else while (ntime.tv_sec > 0) { + delay = (unsigned int)ntime.tv_sec; + + if ((time_t)delay != ntime.tv_sec || delay > 30 * 86400) + delay = 30 * 86400; + + ntime.tv_sec -= delay; + delay = sleep(delay); + ntime.tv_sec += delay; + + if (delay != 0 && report_requested) { + report(ntime.tv_sec, original, ""); + report_requested = 0; + } else + break; + } + + return EXIT_SUCCESS; + /* NOTREACHED */ +} + + /* Reporting does not bother with nanoseconds. */ +static void +report(const time_t remain, const time_t original, const char * const msg) +{ + if (remain == 0) + warnx("In the final moments of the original" + " %jd%s second%s", (intmax_t)original, msg, + original == 1 && *msg == '\0' ? "" : "s"); + else if (remain < 2000) + warnx("Between %jd and %jd seconds left" + " out of the original %g%s", + (intmax_t)remain, (intmax_t)remain + 1, (double)original, + msg); + else if ((original - remain) < 100000 && (original-remain) < original/8) + warnx("Have waited only %jd seconds of the original %g", + (intmax_t)(original - remain), (double)original); + else + warnx("Approximately %g seconds left out of the original %g", + (double)remain, (double)original); +} + +static void +usage(void) +{ + (void)fprintf(stderr, "usage: %s seconds\n", getprogname()); + exit(EXIT_FAILURE); + /* NOTREACHED */ +} + +/* ARGSUSED */ +static void +alarmhandle(int i) +{ + _exit(EXIT_SUCCESS); + /* NOTREACHED */ +} |