xref: /titanic_50/usr/src/lib/libshell/common/bltins/sleep.c (revision 7eea693d6b672899726e75993fddc4e95b52647f)
1 /***********************************************************************
2 *                                                                      *
3 *               This software is part of the ast package               *
4 *           Copyright (c) 1982-2007 AT&T Knowledge Ventures            *
5 *                      and is licensed under the                       *
6 *                  Common Public License, Version 1.0                  *
7 *                      by AT&T Knowledge Ventures                      *
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  *   research!dgk
27  *
28  */
29 
30 #define sleep	______sleep
31 #include	"defs.h"
32 #undef	sleep
33 #include	<error.h>
34 #include	<errno.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;
49 	register Shell_t *shp = (Shell_t*)extra;
50 	time_t tloc = 0;
51 	while((argc = optget(argv,sh_optsleep))) switch(argc)
52 	{
53 		case ':':
54 			errormsg(SH_DICT,2, "%s", opt_info.arg);
55 			break;
56 		case '?':
57 			errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
58 			break;
59 	}
60 	argv += opt_info.index;
61 	if(error_info.errors || !(cp= *argv) || !(strmatch(cp,e_numeric)))
62 		errormsg(SH_DICT,ERROR_usage(2),"%s",optusage((char*)0));
63 	if((d=strtod(cp, (char**)0)) > .10)
64 	{
65 		sfsync(shp->outpool);
66 		time(&tloc);
67 		tloc += (time_t)(d+.5);
68 	}
69 	while(1)
70 	{
71 		time_t now;
72 		errno = 0;
73 		shp->lastsig=0;
74 		sh_delay(d);
75 		if(tloc==0 || errno!=EINTR || shp->lastsig)
76 			break;
77 		sh_sigcheck();
78 		if(tloc < (now=time(NIL(time_t*))))
79 			break;
80 		d = (double)(tloc-now);
81 		if(shp->sigflag[SIGALRM]&SH_SIGTRAP)
82 			sh_timetraps();
83 	}
84 	return(0);
85 }
86 
87 static void completed(void * handle)
88 {
89 	char *expired = (char*)handle;
90 	*expired = 1;
91 }
92 
93 unsigned int sleep(unsigned int sec)
94 {
95 	pid_t newpid, curpid=getpid();
96 	void *tp;
97 	char expired = 0;
98 	sh.lastsig = 0;
99 	tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired);
100 	do
101 	{
102 		if(!sh.waitevent || (*sh.waitevent)(-1,-1L,0)==0)
103 			pause();
104 		if(sh.sigflag[SIGALRM]&SH_SIGTRAP)
105 			sh_timetraps();
106 		if((newpid=getpid()) != curpid)
107 		{
108 			curpid = newpid;
109 			sh.lastsig = 0;
110 			sh.trapnote &= ~SH_SIGSET;
111 			if(expired)
112 				expired = 0;
113 			else
114 				timerdel(tp);
115 			tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired);
116 		}
117 	}
118 	while(!expired && sh.lastsig==0);
119 	if(!expired)
120 		timerdel(tp);
121 	sh_sigcheck();
122 	return(0);
123 }
124 
125 /*
126  * delay execution for time <t>
127  */
128 
129 void	sh_delay(double t)
130 {
131 	register int n = (int)t;
132 #ifdef _lib_poll
133 	struct pollfd fd;
134 	if(t<=0)
135 		return;
136 	else if(n > 30)
137 	{
138 		sleep(n);
139 		t -= n;
140 	}
141 	if(n=(int)(1000*t))
142 	{
143 		if(!sh.waitevent || (*sh.waitevent)(-1,(long)n,0)==0)
144 			poll(&fd,0,n);
145 	}
146 #else
147 #   if defined(_lib_select) && defined(_mem_tv_usec_timeval)
148 	struct timeval timeloc;
149 	if(t<=0)
150 		return;
151 	if(n=(int)(1000*t) && sh.waitevent && (*sh.waitevent)(-1,(long)n,0))
152 		return;
153 	n = (int)t;
154 	timeloc.tv_sec = n;
155 	timeloc.tv_usec = 1000000*(t-(double)n);
156 	select(0,(fd_set*)0,(fd_set*)0,(fd_set*)0,&timeloc);
157 #   else
158 #	ifdef _lib_select
159 		/* for 9th edition machines */
160 		if(t<=0)
161 			return;
162 		if(n > 30)
163 		{
164 			sleep(n);
165 			t -= n;
166 		}
167 		if(n=(int)(1000*t))
168 		{
169 			if(!sh.waitevent || (*sh.waitevent)(-1,(long)n,0)==0)
170 				select(0,(fd_set*)0,(fd_set*)0,n);
171 		}
172 #	else
173 		struct tms tt;
174 		if(t<=0)
175 			return;
176 		sleep(n);
177 		t -= n;
178 		if(t)
179 		{
180 			clock_t begin = times(&tt);
181 			if(begin==0)
182 				return;
183 			t *= sh.lim.clk_tck;
184 			n += (t+.5);
185 			while((times(&tt)-begin) < n);
186 		}
187 #	endif
188 #   endif
189 #endif /* _lib_poll */
190 }
191