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