Home | History | Annotate | Download | only in bltins
      1 /***********************************************************************
      2 *                                                                      *
      3 *               This software is part of the ast package               *
      4 *          Copyright (c) 1982-2009 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 (at) 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