1 # include "sendmail.h"
2 
3 SCCSID(@(#)clock.c	3.4		08/08/82);
4 
5 /*
6 **  SETEVENT -- set an event to happen at a specific time.
7 **
8 **	Parameters:
9 **		intvl -- intvl until next event occurs.
10 **		func -- function to call on event.
11 **		arg -- argument to func on event.
12 **
13 **	Returns:
14 **		none.
15 **
16 **	Side Effects:
17 **		none.
18 */
19 
20 EVENT *
21 setevent(intvl, func, arg)
22 	time_t intvl;
23 	int (*func)();
24 	int arg;
25 {
26 	register EVENT **evp;
27 	register EVENT *ev;
28 	auto time_t now;
29 	extern tick();
30 
31 	(void) time(&now);
32 
33 	/* search event queue for correct position */
34 	for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link)
35 	{
36 		if (ev->ev_time >= now + intvl)
37 			break;
38 	}
39 
40 	/* insert new event */
41 	ev = (EVENT *) xalloc(sizeof *ev);
42 	ev->ev_time = now + intvl;
43 	ev->ev_func = func;
44 	ev->ev_arg = arg;
45 	ev->ev_link = *evp;
46 	*evp = ev;
47 
48 	/* reschedule next clock tick if appropriate */
49 	if (ev == EventQueue)
50 	{
51 		/* we have a new event */
52 		(void) signal(SIGALRM, tick);
53 		(void) alarm(intvl);
54 	}
55 
56 # ifdef DEBUG
57 	if (tTd(5, 2))
58 		printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n",
59 			intvl, now + intvl, func, arg, ev);
60 # endif DEBUG
61 
62 	return (ev);
63 }
64 /*
65 **  CLREVENT -- remove an event from the event queue.
66 **
67 **	Parameters:
68 **		ev -- pointer to event to remove.
69 **
70 **	Returns:
71 **		none.
72 **
73 **	Side Effects:
74 **		arranges for event ev to not happen.
75 */
76 
77 clrevent(ev)
78 	register EVENT *ev;
79 {
80 	register EVENT **evp;
81 
82 # ifdef DEBUG
83 	if (tTd(5, 2))
84 		printf("clrevent: ev=%x\n", ev);
85 # endif DEBUG
86 
87 	/* find the parent event */
88 	for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
89 	{
90 		if (*evp == ev)
91 			break;
92 	}
93 
94 	/* now remove it */
95 	if (*evp == NULL)
96 	{
97 		/* hmmmmm.... must have happened. */
98 		return;
99 	}
100 
101 	*evp = ev->ev_link;
102 	free(ev);
103 }
104 /*
105 **  TICK -- take a clock tick
106 **
107 **	Called by the alarm clock.  This routine runs events as needed.
108 **
109 **	Parameters:
110 **		none.
111 **
112 **	Returns:
113 **		none.
114 **
115 **	Side Effects:
116 **		calls the next function in EventQueue.
117 */
118 
119 tick()
120 {
121 	auto time_t now;
122 	register EVENT *ev;
123 
124 	signal(SIGALRM, SIG_IGN);
125 	(void) time(&now);
126 
127 # ifdef DEBUG
128 	if (tTd(5, 1))
129 		printf("tick: now=%ld\n", now);
130 # endif DEBUG
131 
132 	while (EventQueue != NULL && EventQueue->ev_time <= now)
133 	{
134 		/* process the event on the top of the queue */
135 		ev = EventQueue;
136 		EventQueue = EventQueue->ev_link;
137 # ifdef DEBUG
138 		if (tTd(5, 3))
139 			printf("tick: ev=%x, func=%x, arg=%d\n", ev,
140 				ev->ev_func, ev->ev_arg);
141 # endif DEBUG
142 		(*ev->ev_func)(ev->ev_arg);
143 		free(ev);
144 		(void) time(&now);
145 	}
146 
147 	/* schedule the next clock tick */
148 	signal(SIGALRM, tick);
149 	if (EventQueue != NULL)
150 		(void) alarm(EventQueue->ev_time - now);
151 }
152 /*
153 **  SLEEP -- a version of sleep that works with this stuff
154 **
155 **	Because sleep uses the alarm facility, I must reimplement
156 **	it here.
157 **
158 **	Parameters:
159 **		intvl -- time to sleep.
160 **
161 **	Returns:
162 **		none.
163 **
164 **	Side Effects:
165 **		waits for intvl time.  However, other events can
166 **		be run during that interval.
167 */
168 
169 static bool	SleepDone;
170 
171 sleep(intvl)
172 	int intvl;
173 {
174 	extern endsleep();
175 
176 	SleepDone = FALSE;
177 	setevent(intvl, endsleep, 0);
178 	while (!SleepDone)
179 		pause();
180 }
181 
182 static
183 endsleep()
184 {
185 	SleepDone = TRUE;
186 }
187