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
b_sleep(register int argc,char * argv[],Shbltin_t * context)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
completed(void * handle)130 static void completed(void * handle)
131 {
132 char *expired = (char*)handle;
133 *expired = 1;
134 }
135
sleep(unsigned int sec)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 //
sh_delay(double t)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