xref: /titanic_41/usr/src/lib/libshell/common/bltins/sleep.c (revision 5203bc321053fb87d7073c7640548fab73634793)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *          Copyright (c) 1982-2010 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