00001 /* 00002 sleep implementation using alarm 00003 AUP2, Sec. 9.07.2 00004 00005 Thanks to Geoff Clare for correcting the original version. 00006 00007 Copyright 2003 by Marc J. Rochkind. All rights reserved. 00008 May be copied only for purposes and under conditions described 00009 on the Web page www.basepath.com/aup/copyright.htm. 00010 00011 The Example Files are provided "as is," without any warranty; 00012 without even the implied warranty of merchantability or fitness 00013 for a particular purpose. The author and his publisher are not 00014 responsible for any damages, direct or incidental, resulting 00015 from the use or non-use of these Example Files. 00016 00017 The Example Files may contain defects, and some contain deliberate 00018 coding mistakes that were included for educational reasons. 00019 You are responsible for determining if and how the Example Files 00020 are to be used. 00021 00022 */ 00023 #include "defs.h" 00024 /*[slp_handler]*/ 00025 static void slp_handler(int signum) 00026 { 00027 } 00028 /*[pgm]*/ 00029 unsigned aup_sleep(unsigned secs) 00030 { 00031 sigset_t set, oset; 00032 struct sigaction act, oact; 00033 unsigned prev_alarm, slept, unslept, effective_secs; 00034 00035 ec_neg1( sigemptyset(&set) ) 00036 ec_neg1( sigaddset(&set, SIGALRM) ) 00037 ec_neg1( sigprocmask(SIG_BLOCK, &set, &oset) ) 00038 prev_alarm = alarm(0); 00039 if (prev_alarm != 0 && prev_alarm <= secs) 00040 effective_secs = prev_alarm; 00041 else { 00042 memset(&act, 0, sizeof(act)); 00043 act.sa_handler = slp_handler; 00044 ec_neg1( sigaction(SIGALRM, &act, &oact) ) 00045 effective_secs = secs; 00046 } 00047 alarm(effective_secs); 00048 set = oset; 00049 ec_neg1( sigdelset(&set, SIGALRM) ) 00050 if (sigsuspend(&set) == -1 && errno != EINTR) 00051 EC_FAIL 00052 unslept = alarm(0); 00053 slept = effective_secs - unslept; 00054 ec_neg1( sigaction(SIGALRM, &oact, NULL) ) 00055 if (prev_alarm > slept) 00056 alarm(prev_alarm - slept); 00057 ec_neg1( sigprocmask(SIG_SETMASK, &oset, NULL) ) 00058 return unslept; 00059 00060 EC_CLEANUP_BGN 00061 EC_FLUSH("aup_sleep") 00062 return 0; 00063 EC_CLEANUP_END 00064 } 00065 /*[]*/ 00066 static void alarm_handler(int signum) 00067 { 00068 write(STDOUT_FILENO, "SIGALRM handler\n", 16); 00069 } 00070 00071 int main(void) 00072 { 00073 struct sigaction act; 00074 time_t tm; 00075 00076 memset(&act, 0, sizeof(act)); 00077 act.sa_handler = alarm_handler; 00078 ec_neg1( sigaction(SIGALRM, &act, NULL) ) 00079 time(&tm); 00080 printf("Test 1 -- time %ld\n", (long)tm); 00081 aup_sleep(6); 00082 time(&tm); 00083 printf("Test 2 -- time %ld\n", (long)tm); 00084 alarm(3); 00085 aup_sleep(6); 00086 time(&tm); 00087 printf("Test 3 -- time %ld\n", (long)tm);; 00088 alarm(9); 00089 aup_sleep(6); 00090 time(&tm); 00091 printf("Sleep over; now pausing -- time %ld\n", (long)tm); 00092 pause(); 00093 time(&tm); 00094 printf("Exiting -- time %ld\n", (long)tm); 00095 exit(EXIT_SUCCESS); 00096 00097 EC_CLEANUP_BGN 00098 exit(EXIT_FAILURE); 00099 EC_CLEANUP_END 00100 }