1N/A/***********************************************************************
1N/A* *
1N/A* This software is part of the ast package *
1N/A* Copyright (c) 1982-2011 AT&T Intellectual Property *
1N/A* and is licensed under the *
1N/A* Common Public License, Version 1.0 *
1N/A* by AT&T Intellectual Property *
1N/A* *
1N/A* A copy of the License is available at *
1N/A* http://www.opensource.org/licenses/cpl1.0.txt *
1N/A* (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9) *
1N/A* *
1N/A* Information and Software Systems Research *
1N/A* AT&T Research *
1N/A* Florham Park NJ *
1N/A* *
1N/A* David Korn <dgk@research.att.com> *
1N/A* *
1N/A***********************************************************************/
1N/A#pragma prototyped
1N/A/*
1N/A * sleep delay
1N/A *
1N/A * David Korn
1N/A * AT&T Labs
1N/A *
1N/A */
1N/A
1N/A#define sleep ______sleep
1N/A#include "defs.h"
1N/A#undef sleep
1N/A#include <error.h>
1N/A#include <errno.h>
1N/A#include <tmx.h>
1N/A#include "builtins.h"
1N/A#include "FEATURE/time"
1N/A#include "FEATURE/poll"
1N/A#ifdef _NEXT_SOURCE
1N/A# define sleep _ast_sleep
1N/A#endif /* _NEXT_SOURCE */
1N/A#ifdef _lib_poll_notimer
1N/A# undef _lib_poll
1N/A#endif /* _lib_poll_notimer */
1N/A
1N/Aint b_sleep(register int argc,char *argv[],void *extra)
1N/A{
1N/A register char *cp;
1N/A register double d=0;
1N/A register Shell_t *shp = ((Shbltin_t*)extra)->shp;
1N/A int sflag=0;
1N/A time_t tloc = 0;
1N/A char *last;
1N/A if(!(shp->sigflag[SIGALRM]&(SH_SIGFAULT|SH_SIGOFF)))
1N/A sh_sigtrap(SIGALRM);
1N/A while((argc = optget(argv,sh_optsleep))) switch(argc)
1N/A {
1N/A case 's':
1N/A sflag=1;
1N/A break;
1N/A case ':':
1N/A errormsg(SH_DICT,2, "%s", opt_info.arg);
1N/A break;
1N/A case '?':
1N/A errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
1N/A break;
1N/A }
1N/A argv += opt_info.index;
1N/A if(cp = *argv)
1N/A {
1N/A d = strtod(cp, &last);
1N/A if(*last)
1N/A {
1N/A Time_t now,ns;
1N/A char* pp;
1N/A now = TMX_NOW;
1N/A if(*cp == 'P' || *cp == 'p')
1N/A ns = tmxdate(cp, &last, now);
1N/A else if(*last=='.' && shp->decomma && d==(unsigned long)d)
1N/A {
1N/A *(pp=last) = ',';
1N/A if(!strchr(cp,'.'))
1N/A d = strtod(cp,&last);
1N/A *pp = '.';
1N/A if(*last==0)
1N/A goto skip;
1N/A }
1N/A else if(*last!='.' && *last!=',')
1N/A {
1N/A if(pp = sfprints("exact %s", cp))
1N/A ns = tmxdate(pp, &last, now);
1N/A if(*last && (pp = sfprints("p%s", cp)))
1N/A ns = tmxdate(pp, &last, now);
1N/A }
1N/A if(*last)
1N/A errormsg(SH_DICT,ERROR_exit(1),e_number,*argv);
1N/A d = ns - now;
1N/A d /= TMX_RESOLUTION;
1N/A }
1N/Askip:
1N/A if(argv[1])
1N/A errormsg(SH_DICT,ERROR_exit(1),e_oneoperand);
1N/A }
1N/A else if(!sflag)
1N/A errormsg(SH_DICT,ERROR_exit(1),e_oneoperand);
1N/A if(d > .10)
1N/A {
1N/A time(&tloc);
1N/A tloc += (time_t)(d+.5);
1N/A }
1N/A if(sflag && d==0)
1N/A pause();
1N/A else while(1)
1N/A {
1N/A time_t now;
1N/A errno = 0;
1N/A shp->lastsig=0;
1N/A sh_delay(d);
1N/A if(sflag || tloc==0 || errno!=EINTR || shp->lastsig)
1N/A break;
1N/A sh_sigcheck(shp);
1N/A if(tloc < (now=time(NIL(time_t*))))
1N/A break;
1N/A d = (double)(tloc-now);
1N/A if(shp->sigflag[SIGALRM]&SH_SIGTRAP)
1N/A sh_timetraps(shp);
1N/A }
1N/A return(0);
1N/A}
1N/A
1N/Astatic void completed(void * handle)
1N/A{
1N/A char *expired = (char*)handle;
1N/A *expired = 1;
1N/A}
1N/A
1N/Aunsigned int sleep(unsigned int sec)
1N/A{
1N/A Shell_t *shp = sh_getinterp();
1N/A pid_t newpid, curpid=getpid();
1N/A void *tp;
1N/A char expired = 0;
1N/A shp->lastsig = 0;
1N/A tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired);
1N/A do
1N/A {
1N/A if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,-1L,0)==0)
1N/A pause();
1N/A if(shp->sigflag[SIGALRM]&SH_SIGTRAP)
1N/A sh_timetraps(shp);
1N/A if((newpid=getpid()) != curpid)
1N/A {
1N/A curpid = newpid;
1N/A shp->lastsig = 0;
1N/A shp->trapnote &= ~SH_SIGSET;
1N/A if(expired)
1N/A expired = 0;
1N/A else
1N/A timerdel(tp);
1N/A tp = (void*)sh_timeradd(1000*sec, 0, completed, (void*)&expired);
1N/A }
1N/A }
1N/A while(!expired && shp->lastsig==0);
1N/A if(!expired)
1N/A timerdel(tp);
1N/A sh_sigcheck(shp);
1N/A return(0);
1N/A}
1N/A
1N/A/*
1N/A * delay execution for time <t>
1N/A */
1N/A
1N/Avoid sh_delay(double t)
1N/A{
1N/A register int n = (int)t;
1N/A Shell_t *shp = sh_getinterp();
1N/A#ifdef _lib_poll
1N/A struct pollfd fd;
1N/A if(t<=0)
1N/A return;
1N/A else if(n > 30)
1N/A {
1N/A sleep(n);
1N/A t -= n;
1N/A }
1N/A if(n=(int)(1000*t))
1N/A {
1N/A if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,(long)n,0)==0)
1N/A poll(&fd,0,n);
1N/A }
1N/A#else
1N/A# if defined(_lib_select) && defined(_mem_tv_usec_timeval)
1N/A struct timeval timeloc;
1N/A if(t<=0)
1N/A return;
1N/A if(n=(int)(1000*t) && shp->gd->waitevent && (*shp->gd->waitevent)(-1,(long)n,0))
1N/A return;
1N/A n = (int)t;
1N/A timeloc.tv_sec = n;
1N/A timeloc.tv_usec = 1000000*(t-(double)n);
1N/A select(0,(fd_set*)0,(fd_set*)0,(fd_set*)0,&timeloc);
1N/A# else
1N/A# ifdef _lib_select
1N/A /* for 9th edition machines */
1N/A if(t<=0)
1N/A return;
1N/A if(n > 30)
1N/A {
1N/A sleep(n);
1N/A t -= n;
1N/A }
1N/A if(n=(int)(1000*t))
1N/A {
1N/A if(!shp->gd->waitevent || (*shp->gd->waitevent)(-1,(long)n,0)==0)
1N/A select(0,(fd_set*)0,(fd_set*)0,n);
1N/A }
1N/A# else
1N/A struct tms tt;
1N/A if(t<=0)
1N/A return;
1N/A sleep(n);
1N/A t -= n;
1N/A if(t)
1N/A {
1N/A clock_t begin = times(&tt);
1N/A if(begin==0)
1N/A return;
1N/A t *= shp->gd->lim.clk_tck;
1N/A n += (t+.5);
1N/A while((times(&tt)-begin) < n);
1N/A }
1N/A# endif
1N/A# endif
1N/A#endif /* _lib_poll */
1N/A}