1 # include "sendmail.h"
2 
3 SCCSID(@(#)clock.c	3.3		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 	(void) time(&now);
125 
126 # ifdef DEBUG
127 	if (tTd(5, 1))
128 		printf("tick: now=%ld\n", now);
129 # endif DEBUG
130 
131 	while (EventQueue != NULL && EventQueue->ev_time <= now)
132 	{
133 		/* process the event on the top of the queue */
134 		ev = EventQueue;
135 		EventQueue = EventQueue->ev_link;
136 # ifdef DEBUG
137 		if (tTd(5, 3))
138 			printf("tick: ev=%x, func=%x, arg=%d\n", ev,
139 				ev->ev_func, ev->ev_arg);
140 # endif DEBUG
141 		(*ev->ev_func)(ev->ev_arg);
142 		free(ev);
143 		(void) time(&now);
144 	}
145 
146 	/* schedule the next clock tick */
147 	signal(SIGALRM, tick);
148 	if (EventQueue != NULL)
149 		(void) alarm(EventQueue->ev_time - now);
150 }
151