sleep.c revision 210696
1190558Simp/*-
2190558Simp * Copyright (c) 1988, 1993, 1994
3190558Simp *	The Regents of the University of California.  All rights reserved.
4190558Simp *
5190558Simp * Redistribution and use in source and binary forms, with or without
6190558Simp * modification, are permitted provided that the following conditions
7190558Simp * are met:
8190558Simp * 1. Redistributions of source code must retain the above copyright
9190558Simp *    notice, this list of conditions and the following disclaimer.
10190558Simp * 2. Redistributions in binary form must reproduce the above copyright
11190558Simp *    notice, this list of conditions and the following disclaimer in the
12190558Simp *    documentation and/or other materials provided with the distribution.
13190558Simp * 4. Neither the name of the University nor the names of its contributors
14190558Simp *    may be used to endorse or promote products derived from this software
15190558Simp *    without specific prior written permission.
16190558Simp *
17190558Simp * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18190558Simp * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19190558Simp * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20190558Simp * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21190558Simp * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22190558Simp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23190558Simp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24190558Simp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25190558Simp * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26190558Simp * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27190558Simp * SUCH DAMAGE.
28190558Simp */
29190558Simp
30190558Simp#if 0
31190558Simp#ifndef lint
32190558Simpstatic char const copyright[] =
33190558Simp"@(#) Copyright (c) 1988, 1993, 1994\n\
34190558Simp	The Regents of the University of California.  All rights reserved.\n";
35190558Simp#endif /* not lint */
36190558Simp
37190558Simp#ifndef lint
38190558Simpstatic char sccsid[] = "@(#)sleep.c	8.3 (Berkeley) 4/2/94";
39190558Simp#endif /* not lint */
40190558Simp#endif
41190558Simp#include <sys/cdefs.h>
42190558Simp__FBSDID("$FreeBSD: head/bin/sleep/sleep.c 210696 2010-07-31 17:41:58Z kib $");
43190558Simp
44190558Simp#include <ctype.h>
45190558Simp#include <err.h>
46190558Simp#include <limits.h>
47190558Simp#include <signal.h>
48190558Simp#include <stdint.h>
49190558Simp#include <stdio.h>
50190558Simp#include <stdlib.h>
51190558Simp#include <time.h>
52190558Simp#include <unistd.h>
53190558Simp
54190558Simpstatic void usage(void);
55190558Simp
56190558Simpstatic volatile sig_atomic_t report_requested;
57190558Simpstatic void
58190558Simpreport_request(int signo __unused)
59190558Simp{
60190558Simp
61190558Simp	report_requested = 1;
62190558Simp}
63190558Simp
64190558Simpint
65190558Simpmain(int argc, char *argv[])
66190558Simp{
67190558Simp	struct timespec time_to_sleep;
68190558Simp	long l, original;
69190558Simp	int neg;
70190558Simp	char *p;
71190558Simp
72190558Simp	if (argc != 2)
73190558Simp		usage();
74190558Simp
75190558Simp	p = argv[1];
76190558Simp
77190558Simp	/* Skip over leading whitespaces. */
78190558Simp	while (isspace((unsigned char)*p))
79190558Simp		++p;
80190558Simp
81190558Simp	/* Check for optional `+' or `-' sign. */
82190558Simp	neg = 0;
83190558Simp	if (*p == '-') {
84190558Simp		neg = 1;
85190558Simp		++p;
86190558Simp		if (!isdigit((unsigned char)*p) && *p != '.')
87190558Simp			usage();
88190558Simp	}
89190558Simp	else if (*p == '+')
90190558Simp		++p;
91190558Simp
92190558Simp	/* Calculate seconds. */
93190558Simp	if (isdigit((unsigned char)*p)) {
94190558Simp		l = strtol(p, &p, 10);
95190558Simp
96190558Simp		/*
97190558Simp		 * Avoid overflow when `seconds' is huge.  This assumes
98190558Simp		 * that the maximum value for a time_t is <= INT_MAX.
99213229Smarius		 */
100190558Simp		if (l > INT_MAX)
101190558Simp			l = INT_MAX;
102213364Smarius	} else
103190558Simp		l = 0;
104190558Simp	time_to_sleep.tv_sec = (time_t)l;
105190558Simp
106213364Smarius	/* Calculate nanoseconds. */
107190558Simp	time_to_sleep.tv_nsec = 0;
108190558Simp
109190558Simp	if (*p == '.') {		/* Decimal point. */
110190558Simp		l = 100000000L;
111190558Simp		do {
112190558Simp			if (isdigit((unsigned char)*++p))
113190558Simp				time_to_sleep.tv_nsec += (*p - '0') * l;
114190558Simp			else
115190558Simp				break;
116190558Simp			l /= 10;
117190558Simp		} while (l);
118190558Simp	}
119190558Simp
120190558Simp	/* Skip over the trailing whitespace. */
121190558Simp	while (isspace((unsigned char)*p))
122190558Simp		++p;
123190558Simp	if (*p != '\0')
124190558Simp		usage();
125190558Simp
126190558Simp	signal(SIGINFO, report_request);
127190558Simp	if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0)) {
128190558Simp		original = time_to_sleep.tv_sec;
129190558Simp		while (nanosleep(&time_to_sleep, &time_to_sleep) != 0) {
130190558Simp			if (report_requested) {
131190558Simp				/*
132190558Simp				 * Reporting does not bother with
133190558Simp				 * fractions of a second...
134190558Simp				 */
135190558Simp				warnx("about %jd second(s) left"
136190558Simp				    " out of the original %jd",
137190558Simp				    (intmax_t)time_to_sleep.tv_sec,
138190558Simp				    (intmax_t)original);
139190558Simp				report_requested = 0;
140190558Simp			} else
141190558Simp				break;
142190558Simp		}
143190558Simp	}
144190558Simp
145190558Simp	return (0);
146190558Simp}
147190558Simp
148190558Simpstatic void
149190558Simpusage(void)
150190558Simp{
151190558Simp	static const char msg[] = "usage: sleep seconds\n";
152190558Simp
153190558Simp	write(STDERR_FILENO, msg, sizeof(msg) - 1);
154190558Simp	exit(1);
155190558Simp}
156190558Simp