1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2009 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Common Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.opensource.org/licenses/cpl1.0.txt * 11 * (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * David Korn <dgk@research.att.com> * 18 * * 19 ***********************************************************************/ 20 #pragma prototyped 21 /* 22 * sleep delay 23 * 24 * David Korn 25 * AT&T Labs 26 * 27 */ 28 29 #define sleep ______sleep 30 #include "defs.h" 31 #undef sleep 32 #include <error.h> 33 #include <errno.h> 34 #include <tmx.h> 35 #include "builtins.h" 36 #include "FEATURE/time" 37 #include "FEATURE/poll" 38 #ifdef _NEXT_SOURCE 39 # define sleep _ast_sleep 40 #endif /* _NEXT_SOURCE */ 41 #ifdef _lib_poll_notimer 42 # undef _lib_poll 43 #endif /* _lib_poll_notimer */ 44 45 int b_sleep(register int argc,char *argv[],void *extra) 46 { 47 register char *cp; 48 register double d=0; 49 register Shell_t *shp = ((Shbltin_t*)extra)->shp; 50 int sflag=0; 51 time_t tloc = 0; 52 char *last; 53 if(!(shp->sigflag[SIGALRM]&(SH_SIGFAULT|SH_SIGOFF))) 54 sh_sigtrap(SIGALRM); 55 while((argc = optget(argv,sh_optsleep))) switch(argc) 56 { 57 case 's': 58 sflag=1; 59 break; 60 case ':': 61 errormsg(SH_DICT,2, "%s", opt_info.arg); 62 break; 63 case '?': 64 errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg); 65 break; 66 } 67 argv += opt_info.index; 68 if(cp = *argv) 69 { 70 d = strtod(cp, &last); 71 if(*last) 72 { 73 Time_t now,ns; 74 char* pp; 75 now = TMX_NOW; 76 if(*cp == 'P' || *cp == 'p') 77 ns = tmxdate(cp, &last, now); 78 else 79 { 80 if(pp = sfprints("exact %s", cp)) 81 ns = tmxdate(pp, &last, now); 82 if(*last && (pp = sfprints("p%s", cp))) 83 ns = tmxdate(pp, &last, now); 84 } 85 if(*last) 86 errormsg(SH_DICT,ERROR_exit(1),e_number,*argv); 87 d = ns - now; 88 d /= TMX_RESOLUTION; 89 } 90 if(argv[1]) 91 errormsg(SH_DICT,ERROR_exit(1),e_oneoperand); 92 } 93 else if(!sflag) 94 errormsg(SH_DICT,ERROR_exit(1),e_oneoperand); 95 if(d > .10) 96 { 97 time(&tloc); 98 tloc += (time_t)(d+.5); 99 } 100 if(sflag && d==0) 101 pause(); 102 else while(1) 103 { 104 time_t now; 105 errno = 0; 106 shp->lastsig=0; 107 sh_delay(d); 108 if(sflag || tloc==0 || errno!=EINTR || shp->lastsig) 109 break; 110 sh_sigcheck(); 111 if(tloc < (now=time(NIL(time_t*)))) 112 break; 113 d = (double)(tloc-now); 114 if(shp->sigflag[SIGALRM]&SH_SIGTRAP) 115 sh_timetraps(); 116 } 117 return(0); 118 } 119 120 static void completed(void * handle) 121 { 122 char *expired = (char*)handle; 123 *expired = 1; 124 } 125 126 unsigned int sleep(unsigned int sec) 127 { 128 Shell_t *shp = &sh; 129 pid_t newpid, curpid=getpid(); 130 void *tp; 131 char expired = 0; 132 shp->lastsig = 0; 133 tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired); 134 do 135 { 136 if(!shp->waitevent || (*shp->waitevent)(-1,-1L,0)==0) 137 pause(); 138 if(shp->sigflag[SIGALRM]&SH_SIGTRAP) 139 sh_timetraps(); 140 if((newpid=getpid()) != curpid) 141 { 142 curpid = newpid; 143 shp->lastsig = 0; 144 shp->trapnote &= ~SH_SIGSET; 145 if(expired) 146 expired = 0; 147 else 148 timerdel(tp); 149 tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired); 150 } 151 } 152 while(!expired && shp->lastsig==0); 153 if(!expired) 154 timerdel(tp); 155 sh_sigcheck(); 156 return(0); 157 } 158 159 /* 160 * delay execution for time <t> 161 */ 162 163 void sh_delay(double t) 164 { 165 register int n = (int)t; 166 Shell_t *shp = &sh; 167 #ifdef _lib_poll 168 struct pollfd fd; 169 if(t<=0) 170 return; 171 else if(n > 30) 172 { 173 sleep(n); 174 t -= n; 175 } 176 if(n=(int)(1000*t)) 177 { 178 if(!shp->waitevent || (*shp->waitevent)(-1,(long)n,0)==0) 179 poll(&fd,0,n); 180 } 181 #else 182 # if defined(_lib_select) && defined(_mem_tv_usec_timeval) 183 struct timeval timeloc; 184 if(t<=0) 185 return; 186 if(n=(int)(1000*t) && shp->waitevent && (*shp->waitevent)(-1,(long)n,0)) 187 return; 188 n = (int)t; 189 timeloc.tv_sec = n; 190 timeloc.tv_usec = 1000000*(t-(double)n); 191 select(0,(fd_set*)0,(fd_set*)0,(fd_set*)0,&timeloc); 192 # else 193 # ifdef _lib_select 194 /* for 9th edition machines */ 195 if(t<=0) 196 return; 197 if(n > 30) 198 { 199 sleep(n); 200 t -= n; 201 } 202 if(n=(int)(1000*t)) 203 { 204 if(!shp->waitevent || (*shp->waitevent)(-1,(long)n,0)==0) 205 select(0,(fd_set*)0,(fd_set*)0,n); 206 } 207 # else 208 struct tms tt; 209 if(t<=0) 210 return; 211 sleep(n); 212 t -= n; 213 if(t) 214 { 215 clock_t begin = times(&tt); 216 if(begin==0) 217 return; 218 t *= shp->lim.clk_tck; 219 n += (t+.5); 220 while((times(&tt)-begin) < n); 221 } 222 # endif 223 # endif 224 #endif /* _lib_poll */ 225 } 226