19ddb49cbSWarner Losh /*-
24b88c807SRodney W. Grimes * Copyright (c) 1988, 1993, 1994
34b88c807SRodney W. Grimes * The Regents of the University of California. All rights reserved.
44b88c807SRodney W. Grimes *
54b88c807SRodney W. Grimes * Redistribution and use in source and binary forms, with or without
64b88c807SRodney W. Grimes * modification, are permitted provided that the following conditions
74b88c807SRodney W. Grimes * are met:
84b88c807SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright
94b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer.
104b88c807SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright
114b88c807SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the
124b88c807SRodney W. Grimes * documentation and/or other materials provided with the distribution.
13fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors
144b88c807SRodney W. Grimes * may be used to endorse or promote products derived from this software
154b88c807SRodney W. Grimes * without specific prior written permission.
164b88c807SRodney W. Grimes *
174b88c807SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
184b88c807SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
194b88c807SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
204b88c807SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
214b88c807SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
224b88c807SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
234b88c807SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
244b88c807SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
254b88c807SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
264b88c807SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
274b88c807SRodney W. Grimes * SUCH DAMAGE.
284b88c807SRodney W. Grimes */
294b88c807SRodney W. Grimes
30cd1693d3SConrad Meyer #include <capsicum_helpers.h>
3113d8eedaSKonstantin Belousov #include <err.h>
32c2cfcb60SJilles Tjoelker #include <errno.h>
33ac14c311SRuslan Ermilov #include <limits.h>
34*2295cae7SDag-Erling Smørgrav #include <math.h>
3513d8eedaSKonstantin Belousov #include <signal.h>
36fcfa4c95SMark Murray #include <stdio.h>
374b88c807SRodney W. Grimes #include <stdlib.h>
38ac14c311SRuslan Ermilov #include <time.h>
39*2295cae7SDag-Erling Smørgrav #include <unistd.h>
4013d8eedaSKonstantin Belousov
4113d8eedaSKonstantin Belousov static volatile sig_atomic_t report_requested;
42*2295cae7SDag-Erling Smørgrav
4313d8eedaSKonstantin Belousov static void
report_request(int signo __unused)4413d8eedaSKonstantin Belousov report_request(int signo __unused)
4513d8eedaSKonstantin Belousov {
4613d8eedaSKonstantin Belousov report_requested = 1;
4713d8eedaSKonstantin Belousov }
484b88c807SRodney W. Grimes
49*2295cae7SDag-Erling Smørgrav static void __dead2
usage(void)50*2295cae7SDag-Erling Smørgrav usage(void)
51*2295cae7SDag-Erling Smørgrav {
52*2295cae7SDag-Erling Smørgrav fprintf(stderr, "usage: sleep number[unit] [...]\n"
53*2295cae7SDag-Erling Smørgrav "Unit can be 's' (seconds, the default), "
54*2295cae7SDag-Erling Smørgrav "m (minutes), h (hours), or d (days).\n");
55*2295cae7SDag-Erling Smørgrav exit(1);
56*2295cae7SDag-Erling Smørgrav }
57*2295cae7SDag-Erling Smørgrav
58*2295cae7SDag-Erling Smørgrav static double
parse_interval(const char * arg)59*2295cae7SDag-Erling Smørgrav parse_interval(const char *arg)
60*2295cae7SDag-Erling Smørgrav {
61*2295cae7SDag-Erling Smørgrav double num;
62*2295cae7SDag-Erling Smørgrav char unit, extra;
63*2295cae7SDag-Erling Smørgrav
64*2295cae7SDag-Erling Smørgrav switch (sscanf(arg, "%lf%c%c", &num, &unit, &extra)) {
65*2295cae7SDag-Erling Smørgrav case 2:
66*2295cae7SDag-Erling Smørgrav switch (unit) {
67*2295cae7SDag-Erling Smørgrav case 'd':
68*2295cae7SDag-Erling Smørgrav num *= 24;
69*2295cae7SDag-Erling Smørgrav /* FALLTHROUGH */
70*2295cae7SDag-Erling Smørgrav case 'h':
71*2295cae7SDag-Erling Smørgrav num *= 60;
72*2295cae7SDag-Erling Smørgrav /* FALLTHROUGH */
73*2295cae7SDag-Erling Smørgrav case 'm':
74*2295cae7SDag-Erling Smørgrav num *= 60;
75*2295cae7SDag-Erling Smørgrav /* FALLTHROUGH */
76*2295cae7SDag-Erling Smørgrav case 's':
77*2295cae7SDag-Erling Smørgrav if (!isnan(num))
78*2295cae7SDag-Erling Smørgrav return (num);
79*2295cae7SDag-Erling Smørgrav }
80*2295cae7SDag-Erling Smørgrav break;
81*2295cae7SDag-Erling Smørgrav case 1:
82*2295cae7SDag-Erling Smørgrav if (!isnan(num))
83*2295cae7SDag-Erling Smørgrav return (num);
84*2295cae7SDag-Erling Smørgrav }
85*2295cae7SDag-Erling Smørgrav warnx("invalid time interval: %s", arg);
86*2295cae7SDag-Erling Smørgrav return (INFINITY);
87*2295cae7SDag-Erling Smørgrav }
88*2295cae7SDag-Erling Smørgrav
894b88c807SRodney W. Grimes int
main(int argc,char * argv[])905134c3f7SWarner Losh main(int argc, char *argv[])
914b88c807SRodney W. Grimes {
92ac14c311SRuslan Ermilov struct timespec time_to_sleep;
93*2295cae7SDag-Erling Smørgrav double seconds;
94f6e6dc63SKonstantin Belousov time_t original;
954b88c807SRodney W. Grimes
967672a014SMariusz Zaborski if (caph_limit_stdio() < 0 || caph_enter() < 0)
97cd1693d3SConrad Meyer err(1, "capsicum");
98cd1693d3SConrad Meyer
99*2295cae7SDag-Erling Smørgrav while (getopt(argc, argv, "") != -1)
100*2295cae7SDag-Erling Smørgrav usage();
101*2295cae7SDag-Erling Smørgrav argc -= optind;
102*2295cae7SDag-Erling Smørgrav argv += optind;
103*2295cae7SDag-Erling Smørgrav if (argc < 1)
1044b88c807SRodney W. Grimes usage();
1054b88c807SRodney W. Grimes
106be038c3aSStefan Eßer seconds = 0;
107*2295cae7SDag-Erling Smørgrav while (argc--)
108*2295cae7SDag-Erling Smørgrav seconds += parse_interval(*argv++);
109be038c3aSStefan Eßer if (seconds > INT_MAX)
11013d8eedaSKonstantin Belousov usage();
111*2295cae7SDag-Erling Smørgrav if (seconds < 1e-9)
112*2295cae7SDag-Erling Smørgrav exit(0);
113be038c3aSStefan Eßer original = time_to_sleep.tv_sec = (time_t)seconds;
114be038c3aSStefan Eßer time_to_sleep.tv_nsec = 1e9 * (seconds - time_to_sleep.tv_sec);
11513d8eedaSKonstantin Belousov
11613d8eedaSKonstantin Belousov signal(SIGINFO, report_request);
117c6ef00e3SJilles Tjoelker
11813d8eedaSKonstantin Belousov while (nanosleep(&time_to_sleep, &time_to_sleep) != 0) {
119*2295cae7SDag-Erling Smørgrav if (errno != EINTR)
120*2295cae7SDag-Erling Smørgrav err(1, "nanosleep");
12113d8eedaSKonstantin Belousov if (report_requested) {
122f6e6dc63SKonstantin Belousov /* Reporting does not bother with nanoseconds. */
123*2295cae7SDag-Erling Smørgrav warnx("about %ld second(s) left out of the original %ld",
124*2295cae7SDag-Erling Smørgrav (long)time_to_sleep.tv_sec, (long)original);
12513d8eedaSKonstantin Belousov report_requested = 0;
12613d8eedaSKonstantin Belousov }
1274b88c807SRodney W. Grimes }
1284b88c807SRodney W. Grimes
129*2295cae7SDag-Erling Smørgrav exit(0);
1304b88c807SRodney W. Grimes }
131