xref: /freebsd/bin/sleep/sleep.c (revision 2295cae7e606d75016575927c3d8729745abb17a)
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