xref: /openbsd-src/bin/sleep/sleep.c (revision cb8c274b68edb6c497032f6e02c7e7e16d0c4d21)
1 /*	$OpenBSD: sleep.c,v 1.29 2020/02/25 15:46:15 cheloha 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. Neither the name of the University nor the names of its contributors
17  *    may be used to endorse or promote products derived from this software
18  *    without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30  * SUCH DAMAGE.
31  */
32 
33 #include <sys/time.h>
34 
35 #include <ctype.h>
36 #include <err.h>
37 #include <signal.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <time.h>
41 #include <unistd.h>
42 
43 void alarmh(int);
44 void usage(void);
45 
46 int
main(int argc,char * argv[])47 main(int argc, char *argv[])
48 {
49 	struct timespec rqtp;
50 	time_t t;
51 	char *cp;
52 	int ch, i;
53 
54 	if (pledge("stdio", NULL) == -1)
55 		err(1, "pledge");
56 
57 	signal(SIGALRM, alarmh);
58 
59 	while ((ch = getopt(argc, argv, "")) != -1) {
60 		switch(ch) {
61 		default:
62 			usage();
63 		}
64 	}
65 	argc -= optind;
66 	argv += optind;
67 
68 	if (argc != 1)
69 		usage();
70 
71 	timespecclear(&rqtp);
72 
73 	/* Handle whole seconds. */
74 	for (cp = argv[0]; *cp != '\0' && *cp != '.'; cp++) {
75 		if (!isdigit((unsigned char)*cp))
76 			errx(1, "seconds is invalid: %s", argv[0]);
77 		t = (rqtp.tv_sec * 10) + (*cp - '0');
78 		if (t / 10 != rqtp.tv_sec)	/* overflow */
79 			errx(1, "seconds is too large: %s", argv[0]);
80 		rqtp.tv_sec = t;
81 	}
82 
83 	/*
84 	 * Handle fractions of a second.  The multiplier divides to zero
85 	 * after nine digits so anything more precise than a nanosecond is
86 	 * validated but not used.
87 	 */
88 	if (*cp == '.') {
89 		i = 100000000;
90 		for (cp++; *cp != '\0'; cp++) {
91 			if (!isdigit((unsigned char)*cp))
92 				errx(1, "seconds is invalid: %s", argv[0]);
93 			rqtp.tv_nsec += (*cp - '0') * i;
94 			i /= 10;
95 		}
96 	}
97 
98 	if (timespecisset(&rqtp)) {
99 		if (nanosleep(&rqtp, NULL) == -1)
100 			err(1, "nanosleep");
101 	}
102 
103 	return 0;
104 }
105 
106 void
usage(void)107 usage(void)
108 {
109 	fprintf(stderr, "usage: %s seconds\n", getprogname());
110 	exit(1);
111 }
112 
113 /*
114  * POSIX.1 says sleep(1) may exit with status zero upon receipt
115  * of SIGALRM.
116  */
117 void
alarmh(int signo)118 alarmh(int signo)
119 {
120 	/*
121 	 * Always _exit(2) from signal handlers: exit(3) is not
122 	 * generally signal-safe.
123 	 */
124 	_exit(0);
125 }
126