sleep.c revision 210696
1/*- 2 * Copyright (c) 1988, 1993, 1994 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 4. Neither the name of the University nor the names of its contributors 14 * may be used to endorse or promote products derived from this software 15 * without specific prior written permission. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30#if 0 31#ifndef lint 32static char const copyright[] = 33"@(#) Copyright (c) 1988, 1993, 1994\n\ 34 The Regents of the University of California. All rights reserved.\n"; 35#endif /* not lint */ 36 37#ifndef lint 38static char sccsid[] = "@(#)sleep.c 8.3 (Berkeley) 4/2/94"; 39#endif /* not lint */ 40#endif 41#include <sys/cdefs.h> 42__FBSDID("$FreeBSD: head/bin/sleep/sleep.c 210696 2010-07-31 17:41:58Z kib $"); 43 44#include <ctype.h> 45#include <err.h> 46#include <limits.h> 47#include <signal.h> 48#include <stdint.h> 49#include <stdio.h> 50#include <stdlib.h> 51#include <time.h> 52#include <unistd.h> 53 54static void usage(void); 55 56static volatile sig_atomic_t report_requested; 57static void 58report_request(int signo __unused) 59{ 60 61 report_requested = 1; 62} 63 64int 65main(int argc, char *argv[]) 66{ 67 struct timespec time_to_sleep; 68 long l, original; 69 int neg; 70 char *p; 71 72 if (argc != 2) 73 usage(); 74 75 p = argv[1]; 76 77 /* Skip over leading whitespaces. */ 78 while (isspace((unsigned char)*p)) 79 ++p; 80 81 /* Check for optional `+' or `-' sign. */ 82 neg = 0; 83 if (*p == '-') { 84 neg = 1; 85 ++p; 86 if (!isdigit((unsigned char)*p) && *p != '.') 87 usage(); 88 } 89 else if (*p == '+') 90 ++p; 91 92 /* Calculate seconds. */ 93 if (isdigit((unsigned char)*p)) { 94 l = strtol(p, &p, 10); 95 96 /* 97 * Avoid overflow when `seconds' is huge. This assumes 98 * that the maximum value for a time_t is <= INT_MAX. 99 */ 100 if (l > INT_MAX) 101 l = INT_MAX; 102 } else 103 l = 0; 104 time_to_sleep.tv_sec = (time_t)l; 105 106 /* Calculate nanoseconds. */ 107 time_to_sleep.tv_nsec = 0; 108 109 if (*p == '.') { /* Decimal point. */ 110 l = 100000000L; 111 do { 112 if (isdigit((unsigned char)*++p)) 113 time_to_sleep.tv_nsec += (*p - '0') * l; 114 else 115 break; 116 l /= 10; 117 } while (l); 118 } 119 120 /* Skip over the trailing whitespace. */ 121 while (isspace((unsigned char)*p)) 122 ++p; 123 if (*p != '\0') 124 usage(); 125 126 signal(SIGINFO, report_request); 127 if (!neg && (time_to_sleep.tv_sec > 0 || time_to_sleep.tv_nsec > 0)) { 128 original = time_to_sleep.tv_sec; 129 while (nanosleep(&time_to_sleep, &time_to_sleep) != 0) { 130 if (report_requested) { 131 /* 132 * Reporting does not bother with 133 * fractions of a second... 134 */ 135 warnx("about %jd second(s) left" 136 " out of the original %jd", 137 (intmax_t)time_to_sleep.tv_sec, 138 (intmax_t)original); 139 report_requested = 0; 140 } else 141 break; 142 } 143 } 144 145 return (0); 146} 147 148static void 149usage(void) 150{ 151 static const char msg[] = "usage: sleep seconds\n"; 152 153 write(STDERR_FILENO, msg, sizeof(msg) - 1); 154 exit(1); 155} 156