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