1 /*********************************************************************** 2 * * 3 * This software is part of the ast package * 4 * Copyright (c) 1982-2013 AT&T Intellectual Property * 5 * and is licensed under the * 6 * Eclipse Public License, Version 1.0 * 7 * by AT&T Intellectual Property * 8 * * 9 * A copy of the License is available at * 10 * http://www.eclipse.org/org/documents/epl-v10.html * 11 * (with md5 checksum b35adb5213ca9657e911e9befb180842) * 12 * * 13 * Information and Software Systems Research * 14 * AT&T Research * 15 * Florham Park NJ * 16 * * 17 * David Korn <dgkorn@gmail.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[],Shbltin_t *context) 46 { 47 register char *cp; 48 register double d=0; 49 register Shell_t *shp = context->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 if(*last=='.' && shp->decomma && d==(unsigned long)d) 79 { 80 *(pp=last) = ','; 81 if(!strchr(cp,'.')) 82 d = strtod(cp,&last); 83 *pp = '.'; 84 if(*last==0) 85 goto skip; 86 } 87 else if(*last!='.' && *last!=',') 88 { 89 if(pp = sfprints("exact %s", cp)) 90 ns = tmxdate(pp, &last, now); 91 if(*last && (pp = sfprints("p%s", cp))) 92 ns = tmxdate(pp, &last, now); 93 } 94 if(*last) 95 errormsg(SH_DICT,ERROR_exit(1),e_number,*argv); 96 d = ns - now; 97 d /= TMX_RESOLUTION; 98 } 99 skip: 100 if(argv[1]) 101 errormsg(SH_DICT,ERROR_exit(1),e_oneoperand); 102 } 103 else if(!sflag) 104 errormsg(SH_DICT,ERROR_exit(1),e_oneoperand); 105 if(d > .10) 106 { 107 time(&tloc); 108 tloc += (time_t)(d+.5); 109 } 110 if(sflag && d==0) 111 pause(); 112 else while(1) 113 { 114 time_t now; 115 errno = 0; 116 shp->lastsig=0; 117 sh_delay(d); 118 if(sflag || tloc==0 || errno!=EINTR || shp->lastsig) 119 break; 120 sh_sigcheck(shp); 121 if(tloc < (now=time(NIL(time_t*)))) 122 break; 123 d = (double)(tloc-now); 124 if(shp->sigflag[SIGALRM]&SH_SIGTRAP) 125 sh_timetraps(shp); 126 } 127 return(0); 128 } 129 130 static void completed(void * handle) 131 { 132 char *expired = (char*)handle; 133 *expired = 1; 134 } 135 136 unsigned int sleep(unsigned int sec) 137 { 138 Shell_t *shp = sh_getinterp(); 139 pid_t newpid, curpid=getpid(); 140 void *tp; 141 char expired = 0; 142 shp->lastsig = 0; 143 tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired); 144 do 145 { 146 if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,-1L,0)==0) 147 pause(); 148 if(shp->sigflag[SIGALRM]&SH_SIGTRAP) 149 sh_timetraps(shp); 150 if((newpid=getpid()) != curpid) 151 { 152 curpid = newpid; 153 shp->lastsig = 0; 154 shp->trapnote &= ~SH_SIGSET; 155 if(expired) 156 expired = 0; 157 else 158 timerdel(tp); 159 tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired); 160 } 161 } 162 while(!expired && shp->lastsig==0); 163 if(!expired) 164 timerdel(tp); 165 sh_sigcheck(shp); 166 return(0); 167 } 168 169 // 170 // Delay execution for time <t>. 171 // 172 void sh_delay(double t) { 173 Shell_t *shp = sh_getinterp(); 174 int n = (int)t; 175 Tv_t ts, tx; 176 177 ts.tv_sec = n; 178 ts.tv_nsec = 1000000000 * (t - (double)n); 179 while (tvsleep(&ts, &tx) < 0 && errno == EINTR) { 180 if (shp->trapnote & (SH_SIGSET | SH_SIGTRAP)) return; 181 ts = tx; 182 } 183 } 184