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 18 /* written by Jim Meyering */ 19 20 #ifdef HAVE_CONFIG_H 21 # include <config.h> 22 #endif 23 24 /* Undefine nanosleep here so any prototype is not redefined to be a 25 prototype for rpl_nanosleep. (they'd conflict e.g., on alpha-dec-osf3.2) */ 26 #undef nanosleep 27 28 #include <stdbool.h> 29 #include <stdio.h> 30 #include <sys/types.h> 31 #include <signal.h> 32 33 #include <errno.h> 34 35 #if HAVE_UNISTD_H 36 # include <unistd.h> 37 #endif 38 39 #include "timespec.h" 40 41 /* Some systems (MSDOS) don't have SIGCONT. 42 Using SIGTERM here turns the signal-handling code below 43 into a no-op on such systems. */ 44 #ifndef SIGCONT 45 # define SIGCONT SIGTERM 46 #endif 47 48 #if ! HAVE_SIGINTERRUPT 49 # define siginterrupt(sig, flag) /* empty */ 50 #endif 51 52 static sig_atomic_t volatile suspended; 53 54 /* Handle SIGCONT. */ 55 56 static void 57 sighandler (int sig) 58 { 59 suspended = 1; 60 } 61 62 /* FIXME: comment */ 63 64 static void 65 my_usleep (const struct timespec *ts_delay) 66 { 67 struct timeval tv_delay; 68 tv_delay.tv_sec = ts_delay->tv_sec; 69 tv_delay.tv_usec = (ts_delay->tv_nsec + 999) / 1000; 70 if (tv_delay.tv_usec == 1000000) 71 { 72 tv_delay.tv_sec++; 73 tv_delay.tv_usec = 0; 74 } 75 select (0, NULL, NULL, NULL, &tv_delay); 76 } 77 78 /* FIXME: comment */ 79 80 int 81 rpl_nanosleep (const struct timespec *requested_delay, 82 struct timespec *remaining_delay) 83 { 84 static bool initialized; 85 86 /* set up sig handler */ 87 if (! initialized) 88 { 89 #ifdef SA_NOCLDSTOP 90 struct sigaction oldact, newact; 91 newact.sa_handler = sighandler; 92 sigemptyset (&newact.sa_mask); 93 newact.sa_flags = 0; 94 95 sigaction (SIGCONT, NULL, &oldact); 96 if (oldact.sa_handler != SIG_IGN) 97 sigaction (SIGCONT, &newact, NULL); 98 #else 99 if (signal (SIGCONT, SIG_IGN) != SIG_IGN) 100 { 101 signal (SIGCONT, sighandler); 102 siginterrupt (SIGCONT, 1); 103 } 104 #endif 105 initialized = true; 106 } 107 108 suspended = 0; 109 110 my_usleep (requested_delay); 111 112 if (suspended) 113 { 114 /* Calculate time remaining. */ 115 /* FIXME: the code in sleep doesn't use this, so there's no 116 rush to implement it. */ 117 118 errno = EINTR; 119 } 120 121 /* FIXME: Restore sig handler? */ 122 123 return suspended; 124 } 125