1/***********************************************************************
2*                                                                      *
3*               This software is part of the ast package               *
4*          Copyright (c) 1982-2012 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 <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
45int	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		}
99skip:
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
130static void completed(void * handle)
131{
132	char *expired = (char*)handle;
133	*expired = 1;
134}
135
136unsigned 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
173void	sh_delay(double t)
174{
175	register int n = (int)t;
176	Shell_t	*shp = sh_getinterp();
177#ifdef _lib_poll
178	struct pollfd fd;
179	if(t<=0)
180		return;
181	else if(n > 30)
182	{
183		sleep(n);
184		t -= n;
185	}
186	if(n=(int)(1000*t))
187	{
188		if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,(long)n,0)==0)
189			poll(&fd,0,n);
190	}
191#else
192#   if defined(_lib_select) && defined(_mem_tv_usec_timeval)
193	struct timeval timeloc;
194	if(t<=0)
195		return;
196	if(n=(int)(1000*t) && shp->gd->waitevent && (*shp->gd->waitevent)(-1,(long)n,0))
197		return;
198	n = (int)t;
199	timeloc.tv_sec = n;
200	timeloc.tv_usec = 1000000*(t-(double)n);
201	select(0,(fd_set*)0,(fd_set*)0,(fd_set*)0,&timeloc);
202#   else
203#	ifdef _lib_select
204		/* for 9th edition machines */
205		if(t<=0)
206			return;
207		if(n > 30)
208		{
209			sleep(n);
210			t -= n;
211		}
212		if(n=(int)(1000*t))
213		{
214			if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,(long)n,0)==0)
215				select(0,(fd_set*)0,(fd_set*)0,n);
216		}
217#	else
218		struct tms tt;
219		if(t<=0)
220			return;
221		sleep(n);
222		t -= n;
223		if(t)
224		{
225			clock_t begin = times(&tt);
226			if(begin==0)
227				return;
228			t *= shp->gd->lim.clk_tck;
229			n += (t+.5);
230			while((times(&tt)-begin) < n);
231		}
232#	endif
233#   endif
234#endif /* _lib_poll */
235}
236