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