xref: /onnv-gate/usr/src/lib/libshell/common/bltins/alarm.c (revision 12068:08a39a083754)
14887Schin /***********************************************************************
24887Schin *                                                                      *
34887Schin *               This software is part of the ast package               *
4*12068SRoger.Faulkner@Oracle.COM *          Copyright (c) 1982-2010 AT&T Intellectual Property          *
54887Schin *                      and is licensed under the                       *
64887Schin *                  Common Public License, Version 1.0                  *
78462SApril.Chin@Sun.COM *                    by AT&T Intellectual Property                     *
84887Schin *                                                                      *
94887Schin *                A copy of the License is available at                 *
104887Schin *            http://www.opensource.org/licenses/cpl1.0.txt             *
114887Schin *         (with md5 checksum 059e8cd6165cb4c31e351f2b69388fd9)         *
124887Schin *                                                                      *
134887Schin *              Information and Software Systems Research               *
144887Schin *                            AT&T Research                             *
154887Schin *                           Florham Park NJ                            *
164887Schin *                                                                      *
174887Schin *                  David Korn <dgk@research.att.com>                   *
184887Schin *                                                                      *
194887Schin ***********************************************************************/
204887Schin #pragma prototyped
214887Schin /*
224887Schin  * alarm [-r] [varname [+]when]
234887Schin  *
244887Schin  *   David Korn
254887Schin  *   AT&T Labs
264887Schin  *
274887Schin  */
284887Schin 
294887Schin #include	"defs.h"
304887Schin #include	<error.h>
314887Schin #include	<stak.h>
324887Schin #include	"builtins.h"
334887Schin #include	"FEATURE/time"
344887Schin 
354887Schin #define R_FLAG	1
364887Schin #define L_FLAG	2
374887Schin 
384887Schin struct	tevent
394887Schin {
404887Schin 	Namfun_t	fun;
414887Schin 	Namval_t	*node;
424887Schin 	Namval_t	*action;
434887Schin 	struct tevent	*next;
444887Schin 	long		milli;
454887Schin 	int		flags;
464887Schin 	void            *timeout;
474887Schin 	Shell_t		*sh;
484887Schin };
494887Schin 
504887Schin static const char ALARM[] = "alarm";
514887Schin 
524887Schin static void	trap_timeout(void*);
534887Schin 
544887Schin /*
554887Schin  * insert timeout item on current given list in sorted order
564887Schin  */
time_add(struct tevent * item,void * list)574887Schin static void *time_add(struct tevent *item, void *list)
584887Schin {
594887Schin 	register struct tevent *tp = (struct tevent*)list;
604887Schin 	if(!tp || item->milli < tp->milli)
614887Schin 	{
624887Schin 		item->next = tp;
634887Schin 		list = (void*)item;
644887Schin 	}
654887Schin 	else
664887Schin 	{
674887Schin 		while(tp->next && item->milli > tp->next->milli)
684887Schin 			tp = tp->next;
694887Schin 		item->next = tp->next;
704887Schin 		tp->next = item;
714887Schin 	}
724887Schin 	tp = item;
734887Schin 	tp->timeout = (void*)sh_timeradd(tp->milli,tp->flags&R_FLAG,trap_timeout,(void*)tp);
744887Schin 	return(list);
754887Schin }
764887Schin 
774887Schin /*
784887Schin  * delete timeout item from current given list, delete timer
794887Schin  */
time_delete(register struct tevent * item,void * list)804887Schin static 	void *time_delete(register struct tevent *item, void *list)
814887Schin {
824887Schin 	register struct tevent *tp = (struct tevent*)list;
834887Schin 	if(item==tp)
844887Schin 		list = (void*)tp->next;
854887Schin 	else
864887Schin 	{
874887Schin 		while(tp && tp->next != item)
884887Schin 			tp = tp->next;
894887Schin 		if(tp)
904887Schin 			tp->next = item->next;
914887Schin 	}
924887Schin 	if(item->timeout)
934887Schin 		timerdel((void*)item->timeout);
944887Schin 	return(list);
954887Schin }
964887Schin 
print_alarms(void * list)974887Schin static void	print_alarms(void *list)
984887Schin {
994887Schin 	register struct tevent *tp = (struct tevent*)list;
1004887Schin 	while(tp)
1014887Schin 	{
1024887Schin 		if(tp->timeout)
1034887Schin 		{
1044887Schin 			register char *name = nv_name(tp->node);
1054887Schin 			if(tp->flags&R_FLAG)
1064887Schin 			{
1074887Schin 				double d = tp->milli;
1084887Schin 				sfprintf(sfstdout,e_alrm1,name,d/1000.);
1094887Schin 			}
1104887Schin 			else
1114887Schin 				sfprintf(sfstdout,e_alrm2,name,nv_getnum(tp->node));
1124887Schin 		}
1134887Schin 		tp = tp->next;
1144887Schin 	}
1154887Schin }
1164887Schin 
trap_timeout(void * handle)1174887Schin static void	trap_timeout(void* handle)
1184887Schin {
1194887Schin 	register struct tevent *tp = (struct tevent*)handle;
1204887Schin 	tp->sh->trapnote |= SH_SIGALRM;
1214887Schin 	if(!(tp->flags&R_FLAG))
1224887Schin 		tp->timeout = 0;
1234887Schin 	tp->flags |= L_FLAG;
1244887Schin 	tp->sh->sigflag[SIGALRM] |= SH_SIGALRM;
1254887Schin 	if(sh_isstate(SH_TTYWAIT))
1264887Schin 		sh_timetraps();
1274887Schin }
1284887Schin 
sh_timetraps(void)1294887Schin void	sh_timetraps(void)
1304887Schin {
1314887Schin 	register struct tevent *tp, *tpnext;
1324887Schin 	register struct tevent *tptop;
1334887Schin 	while(1)
1344887Schin 	{
1354887Schin 		sh.sigflag[SIGALRM] &= ~SH_SIGALRM;
1364887Schin 		tptop= (struct tevent*)sh.st.timetrap;
1374887Schin 		for(tp=tptop;tp;tp=tpnext)
1384887Schin 		{
1394887Schin 			tpnext = tp->next;
1404887Schin 			if(tp->flags&L_FLAG)
1414887Schin 			{
1424887Schin 				tp->flags &= ~L_FLAG;
1434887Schin 				if(tp->action)
1444887Schin 					sh_fun(tp->action,tp->node,(char**)0);
1454887Schin 				tp->flags &= ~L_FLAG;
1464887Schin 				if(!tp->flags)
1474887Schin 				{
1484887Schin 					nv_unset(tp->node);
1494887Schin 					nv_close(tp->node);
1504887Schin 				}
1514887Schin 			}
1524887Schin 		}
1534887Schin 		if(!(sh.sigflag[SIGALRM]&SH_SIGALRM))
1544887Schin 			break;
1554887Schin 	}
1564887Schin }
1574887Schin 
1584887Schin 
1594887Schin /*
1604887Schin  * This trap function catches "alarm" actions only
1614887Schin  */
setdisc(Namval_t * np,const char * event,Namval_t * action,Namfun_t * fp)1624887Schin static char *setdisc(Namval_t *np, const char *event, Namval_t* action, Namfun_t
1634887Schin  *fp)
1644887Schin {
1654887Schin         register struct tevent *tp = (struct tevent*)fp;
1664887Schin 	if(!event)
1674887Schin 		return(action?"":(char*)ALARM);
1684887Schin 	if(strcmp(event,ALARM)!=0)
1694887Schin 	{
1704887Schin 		/* try the next level */
1714887Schin 		return(nv_setdisc(np, event, action, fp));
1724887Schin 	}
1734887Schin 	if(action==np)
1744887Schin 		action = tp->action;
1754887Schin 	else
1764887Schin 		tp->action = action;
1774887Schin 	return(action?(char*)action:"");
1784887Schin }
1794887Schin 
1804887Schin /*
1814887Schin  * catch assignments and set alarm traps
1824887Schin  */
putval(Namval_t * np,const char * val,int flag,Namfun_t * fp)1834887Schin static void putval(Namval_t* np, const char* val, int flag, Namfun_t* fp)
1844887Schin {
1854887Schin 	register struct tevent *tp;
1864887Schin 	register double d;
1874887Schin 	if(val)
1884887Schin 	{
1894887Schin 		double now;
1904887Schin #ifdef timeofday
1914887Schin 		struct timeval tmp;
1924887Schin 		timeofday(&tmp);
1934887Schin 		now = tmp.tv_sec + 1.e-6*tmp.tv_usec;
1944887Schin #else
1954887Schin 		now = (double)time(NIL(time_t*));
1964887Schin #endif /* timeofday */
1974887Schin 		nv_putv(np,val,flag,fp);
1984887Schin 		d = nv_getnum(np);
1994887Schin 		tp = (struct tevent*)fp;
2004887Schin 		if(*val=='+')
2014887Schin 		{
2024887Schin 			double x = d + now;
2034887Schin 			nv_putv(np,(char*)&x,NV_INTEGER,fp);
2044887Schin 		}
2054887Schin 		else
2064887Schin 			d -= now;
2074887Schin 		tp->milli = 1000*(d+.0005);
2084887Schin 		if(tp->timeout)
2094887Schin 			sh.st.timetrap = time_delete(tp,sh.st.timetrap);
2104887Schin 		if(tp->milli > 0)
2114887Schin 			sh.st.timetrap = time_add(tp,sh.st.timetrap);
2124887Schin 	}
2134887Schin 	else
2144887Schin 	{
2154887Schin 		tp = (struct tevent*)nv_stack(np, (Namfun_t*)0);
2164887Schin 		sh.st.timetrap = time_delete(tp,sh.st.timetrap);
2174887Schin 		if(tp->action)
2184887Schin 			nv_close(tp->action);
2194887Schin 		nv_unset(np);
2204887Schin 		free((void*)fp);
2214887Schin 	}
2224887Schin }
2234887Schin 
2244887Schin static const Namdisc_t alarmdisc =
2254887Schin {
2264887Schin 	sizeof(struct tevent),
2274887Schin 	putval,
2284887Schin 	0,
2294887Schin 	0,
2304887Schin 	setdisc,
2314887Schin };
2324887Schin 
b_alarm(int argc,char * argv[],void * extra)2334887Schin int	b_alarm(int argc,char *argv[],void *extra)
2344887Schin {
2354887Schin 	register int n,rflag=0;
2364887Schin 	register Namval_t *np;
2374887Schin 	register struct tevent *tp;
2388462SApril.Chin@Sun.COM 	register Shell_t *shp = ((Shbltin_t*)extra)->shp;
2394887Schin 	while (n = optget(argv, sh_optalarm)) switch (n)
2404887Schin 	{
2414887Schin 	    case 'r':
2424887Schin 		rflag = R_FLAG;
2434887Schin 		break;
2444887Schin 	    case ':':
2454887Schin 		errormsg(SH_DICT,2, "%s", opt_info.arg);
2464887Schin 		break;
2474887Schin 	    case '?':
2484887Schin 		errormsg(SH_DICT,ERROR_usage(2), "%s", opt_info.arg);
2494887Schin 		break;
2504887Schin 	}
2514887Schin 	argc -= opt_info.index;
2524887Schin 	argv += opt_info.index;
2534887Schin 	if(error_info.errors)
2544887Schin 		errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
2554887Schin 	if(argc==0)
2564887Schin 	{
2574887Schin 		print_alarms(shp->st.timetrap);
2584887Schin 		return(0);
2594887Schin 	}
2604887Schin 	if(argc!=2)
2614887Schin 		errormsg(SH_DICT,ERROR_usage(2),optusage((char*)0));
2624887Schin 	np = nv_open(argv[0],shp->var_tree,NV_NOARRAY|NV_VARNAME|NV_NOASSIGN);
2634887Schin 	if(!nv_isnull(np))
2644887Schin 		nv_unset(np);
2658462SApril.Chin@Sun.COM 	nv_setattr(np, NV_DOUBLE);
2664887Schin 	if(!(tp = newof(NIL(struct tevent*),struct tevent,1,0)))
2674887Schin 		errormsg(SH_DICT,ERROR_exit(1),e_nospace);
2684887Schin 	tp->fun.disc = &alarmdisc;
2694887Schin 	tp->flags = rflag;
2704887Schin 	tp->node = np;
2714887Schin 	tp->sh = shp;
2724887Schin 	nv_stack(np,(Namfun_t*)tp);
2734887Schin 	nv_putval(np, argv[1], 0);
2744887Schin 	return(0);
2754887Schin }
2764887Schin 
277