xref: /openbsd-src/bin/sleep/sleep.c (revision b2ea75c1b17e1a9a339660e7ed45cd24946b230e)
1 /*	$OpenBSD: sleep.c,v 1.10 2001/05/20 08:04:48 mickey Exp $	*/
2 /*	$NetBSD: sleep.c,v 1.8 1995/03/21 09:11:11 cgd Exp $	*/
3 
4 /*
5  * Copyright (c) 1988, 1993, 1994
6  *	The Regents of the University of California.  All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  * 1. Redistributions of source code must retain the above copyright
12  *    notice, this list of conditions and the following disclaimer.
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  * 3. All advertising materials mentioning features or use of this software
17  *    must display the following acknowledgement:
18  *	This product includes software developed by the University of
19  *	California, Berkeley and its contributors.
20  * 4. Neither the name of the University nor the names of its contributors
21  *    may be used to endorse or promote products derived from this software
22  *    without specific prior written permission.
23  *
24  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34  * SUCH DAMAGE.
35  */
36 
37 #ifndef lint
38 static char copyright[] =
39 "@(#) Copyright (c) 1988, 1993, 1994\n\
40 	The Regents of the University of California.  All rights reserved.\n";
41 #endif /* not lint */
42 
43 #ifndef lint
44 #if 0
45 static char sccsid[] = "@(#)sleep.c	8.3 (Berkeley) 4/2/94";
46 #else
47 static char rcsid[] = "$OpenBSD: sleep.c,v 1.10 2001/05/20 08:04:48 mickey Exp $";
48 #endif
49 #endif /* not lint */
50 
51 #include <ctype.h>
52 #include <errno.h>
53 #include <locale.h>
54 #include <signal.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <time.h>
58 #include <unistd.h>
59 
60 void usage __P((void));
61 void alarmh __P((int));
62 
63 int
64 main(argc, argv)
65 	int argc;
66 	char *argv[];
67 {
68 	int ch;
69 	time_t secs = 0, t;
70 	unsigned char *cp;
71 	long nsecs = 0;
72 	struct timespec rqtp;
73 	int i;
74 
75 	setlocale(LC_ALL, "");
76 
77 	signal(SIGALRM, alarmh);
78 
79 	while ((ch = getopt(argc, argv, "")) != -1)
80 		switch(ch) {
81 		case '?':
82 		case 'h':
83 		default:
84 			usage();
85 		}
86 	argc -= optind;
87 	argv += optind;
88 
89 	if (argc != 1)
90 		usage();
91 
92 	cp = *argv;
93 	while ((*cp != '\0') && (*cp != '.')) {
94 		if (!isdigit(*cp)) usage();
95 		t = (secs * 10) + (*cp++ - '0');
96 		if (t / 10 != secs)	/* oflow */
97 			return (EINVAL);
98 		secs = t;
99 	}
100 
101 	/* Handle fractions of a second */
102 	if (*cp == '.') {
103 		*cp++ = '\0';
104 		for (i = 100000000; i > 0; i /= 10) {
105 			if (*cp == '\0') break;
106 			if (!isdigit(*cp)) usage();
107 			nsecs += (*cp++ - '0') * i;
108 		}
109 
110 		/*
111 		 * We parse all the way down to nanoseconds
112 		 * in the above for loop. Be pedantic about
113 		 * checking the rest of the argument.
114 		 */
115 		while (*cp != '\0') {
116 			if (!isdigit(*cp++)) usage();
117 		}
118 	}
119 
120 	rqtp.tv_sec = secs;
121 	rqtp.tv_nsec = nsecs;
122 
123 	if ((secs > 0) || (nsecs > 0))
124 		if (nanosleep(&rqtp, NULL))
125 			return (errno);
126 	return (0);
127 }
128 
129 void
130 usage()
131 {
132 
133 	(void)fprintf(stderr, "usage: sleep seconds\n");
134 	exit(1);
135 }
136 
137 /*
138  * POSIX 1003.2 says sleep should exit with 0 return code on reception
139  * of SIGALRM.
140  */
141 void
142 alarmh(sigraised)
143 	int sigraised;
144 {
145 	/*
146 	 * exit() flushes stdio buffers, which is not legal in a signal
147 	 * handler. Use _exit().
148 	 */
149 	_exit(0);
150 }
151