1a7c91847Schristos /* Provide a replacement for the POSIX nanosleep function.
2a7c91847Schristos Copyright (C) 1999, 2000, 2002, 2004, 2005 Free Software Foundation, Inc.
3a7c91847Schristos
4a7c91847Schristos This program is free software; you can redistribute it and/or modify
5a7c91847Schristos it under the terms of the GNU General Public License as published by
6a7c91847Schristos the Free Software Foundation; either version 2, or (at your option)
7a7c91847Schristos any later version.
8a7c91847Schristos
9a7c91847Schristos This program is distributed in the hope that it will be useful,
10a7c91847Schristos but WITHOUT ANY WARRANTY; without even the implied warranty of
11a7c91847Schristos MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12a7c91847Schristos GNU General Public License for more details.
13a7c91847Schristos
14a7c91847Schristos You should have received a copy of the GNU General Public License
15a7c91847Schristos along with this program; if not, write to the Free Software Foundation,
16a7c91847Schristos Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
17*5a6c14c8Schristos #include <sys/cdefs.h>
18*5a6c14c8Schristos __RCSID("$NetBSD: nanosleep.c,v 1.2 2016/05/17 14:00:09 christos Exp $");
19*5a6c14c8Schristos
20a7c91847Schristos
21a7c91847Schristos /* written by Jim Meyering */
22a7c91847Schristos
23a7c91847Schristos #ifdef HAVE_CONFIG_H
24a7c91847Schristos # include <config.h>
25a7c91847Schristos #endif
26a7c91847Schristos
27a7c91847Schristos /* Undefine nanosleep here so any prototype is not redefined to be a
28a7c91847Schristos prototype for rpl_nanosleep. (they'd conflict e.g., on alpha-dec-osf3.2) */
29a7c91847Schristos #undef nanosleep
30a7c91847Schristos
31a7c91847Schristos #include <stdbool.h>
32a7c91847Schristos #include <stdio.h>
33a7c91847Schristos #include <sys/types.h>
34a7c91847Schristos #include <signal.h>
35a7c91847Schristos
36a7c91847Schristos #include <errno.h>
37a7c91847Schristos
38a7c91847Schristos #if HAVE_UNISTD_H
39a7c91847Schristos # include <unistd.h>
40a7c91847Schristos #endif
41a7c91847Schristos
42a7c91847Schristos #include "timespec.h"
43a7c91847Schristos
44a7c91847Schristos /* Some systems (MSDOS) don't have SIGCONT.
45a7c91847Schristos Using SIGTERM here turns the signal-handling code below
46a7c91847Schristos into a no-op on such systems. */
47a7c91847Schristos #ifndef SIGCONT
48a7c91847Schristos # define SIGCONT SIGTERM
49a7c91847Schristos #endif
50a7c91847Schristos
51a7c91847Schristos #if ! HAVE_SIGINTERRUPT
52a7c91847Schristos # define siginterrupt(sig, flag) /* empty */
53a7c91847Schristos #endif
54a7c91847Schristos
55a7c91847Schristos static sig_atomic_t volatile suspended;
56a7c91847Schristos
57a7c91847Schristos /* Handle SIGCONT. */
58a7c91847Schristos
59a7c91847Schristos static void
sighandler(int sig)60a7c91847Schristos sighandler (int sig)
61a7c91847Schristos {
62a7c91847Schristos suspended = 1;
63a7c91847Schristos }
64a7c91847Schristos
65a7c91847Schristos /* FIXME: comment */
66a7c91847Schristos
67a7c91847Schristos static void
my_usleep(const struct timespec * ts_delay)68a7c91847Schristos my_usleep (const struct timespec *ts_delay)
69a7c91847Schristos {
70a7c91847Schristos struct timeval tv_delay;
71a7c91847Schristos tv_delay.tv_sec = ts_delay->tv_sec;
72a7c91847Schristos tv_delay.tv_usec = (ts_delay->tv_nsec + 999) / 1000;
73a7c91847Schristos if (tv_delay.tv_usec == 1000000)
74a7c91847Schristos {
75a7c91847Schristos tv_delay.tv_sec++;
76a7c91847Schristos tv_delay.tv_usec = 0;
77a7c91847Schristos }
78a7c91847Schristos select (0, NULL, NULL, NULL, &tv_delay);
79a7c91847Schristos }
80a7c91847Schristos
81a7c91847Schristos /* FIXME: comment */
82a7c91847Schristos
83a7c91847Schristos int
rpl_nanosleep(const struct timespec * requested_delay,struct timespec * remaining_delay)84a7c91847Schristos rpl_nanosleep (const struct timespec *requested_delay,
85a7c91847Schristos struct timespec *remaining_delay)
86a7c91847Schristos {
87a7c91847Schristos static bool initialized;
88a7c91847Schristos
89a7c91847Schristos /* set up sig handler */
90a7c91847Schristos if (! initialized)
91a7c91847Schristos {
92a7c91847Schristos #ifdef SA_NOCLDSTOP
93a7c91847Schristos struct sigaction oldact, newact;
94a7c91847Schristos newact.sa_handler = sighandler;
95a7c91847Schristos sigemptyset (&newact.sa_mask);
96a7c91847Schristos newact.sa_flags = 0;
97a7c91847Schristos
98a7c91847Schristos sigaction (SIGCONT, NULL, &oldact);
99a7c91847Schristos if (oldact.sa_handler != SIG_IGN)
100a7c91847Schristos sigaction (SIGCONT, &newact, NULL);
101a7c91847Schristos #else
102a7c91847Schristos if (signal (SIGCONT, SIG_IGN) != SIG_IGN)
103a7c91847Schristos {
104a7c91847Schristos signal (SIGCONT, sighandler);
105a7c91847Schristos siginterrupt (SIGCONT, 1);
106a7c91847Schristos }
107a7c91847Schristos #endif
108a7c91847Schristos initialized = true;
109a7c91847Schristos }
110a7c91847Schristos
111a7c91847Schristos suspended = 0;
112a7c91847Schristos
113a7c91847Schristos my_usleep (requested_delay);
114a7c91847Schristos
115a7c91847Schristos if (suspended)
116a7c91847Schristos {
117a7c91847Schristos /* Calculate time remaining. */
118a7c91847Schristos /* FIXME: the code in sleep doesn't use this, so there's no
119a7c91847Schristos rush to implement it. */
120a7c91847Schristos
121a7c91847Schristos errno = EINTR;
122a7c91847Schristos }
123a7c91847Schristos
124a7c91847Schristos /* FIXME: Restore sig handler? */
125a7c91847Schristos
126a7c91847Schristos return suspended;
127a7c91847Schristos }
128