overhaul status of SMTP reply codes
[unix-history] / usr / src / usr.sbin / sendmail / src / clock.c
CommitLineData
d185cb11 1/*
dc45ba8c 2 * Copyright (c) 1983 Eric P. Allman
bee79b64
KB
3 * Copyright (c) 1988 Regents of the University of California.
4 * All rights reserved.
5 *
417f7a11 6 * %sccs.include.redist.c%
bee79b64 7 */
d185cb11
DF
8
9#ifndef lint
b6edea3d 10static char sccsid[] = "@(#)clock.c 6.2 (Berkeley) %G%";
bee79b64 11#endif /* not lint */
d185cb11 12
78eeba87 13# include "sendmail.h"
671d4b5c 14# include <signal.h>
78eeba87 15
78eeba87 16/*
2439b900
EA
17** SETEVENT -- set an event to happen at a specific time.
18**
7338e3d4
EA
19** Events are stored in a sorted list for fast processing.
20** An event only applies to the process that set it.
21**
2439b900
EA
22** Parameters:
23** intvl -- intvl until next event occurs.
24** func -- function to call on event.
25** arg -- argument to func on event.
26**
27** Returns:
28** none.
29**
30** Side Effects:
31** none.
32*/
33
0df908a9
KB
34static void tick();
35
2439b900
EA
36EVENT *
37setevent(intvl, func, arg)
38 time_t intvl;
39 int (*func)();
40 int arg;
41{
42 register EVENT **evp;
43 register EVENT *ev;
44 auto time_t now;
2439b900 45
1d743b8b
EA
46 if (intvl <= 0)
47 {
b6edea3d 48 syserr("554 setevent: intvl=%ld\n", intvl);
611b763d 49 return (NULL);
1d743b8b 50 }
1d743b8b 51
2439b900
EA
52 (void) time(&now);
53
54 /* search event queue for correct position */
55 for (evp = &EventQueue; (ev = *evp) != NULL; evp = &ev->ev_link)
56 {
57 if (ev->ev_time >= now + intvl)
58 break;
59 }
60
61 /* insert new event */
62 ev = (EVENT *) xalloc(sizeof *ev);
63 ev->ev_time = now + intvl;
64 ev->ev_func = func;
65 ev->ev_arg = arg;
f5d25d7b 66 ev->ev_pid = getpid();
2439b900
EA
67 ev->ev_link = *evp;
68 *evp = ev;
69
aa4ef64d 70 if (tTd(5, 5))
2439b900
EA
71 printf("setevent: intvl=%ld, for=%ld, func=%x, arg=%d, ev=%x\n",
72 intvl, now + intvl, func, arg, ev);
2439b900 73
6d06102a 74 tick();
2439b900
EA
75 return (ev);
76}
77\f/*
78** CLREVENT -- remove an event from the event queue.
79**
80** Parameters:
81** ev -- pointer to event to remove.
82**
83** Returns:
84** none.
85**
86** Side Effects:
87** arranges for event ev to not happen.
88*/
89
90clrevent(ev)
91 register EVENT *ev;
92{
93 register EVENT **evp;
94
aa4ef64d 95 if (tTd(5, 5))
2439b900 96 printf("clrevent: ev=%x\n", ev);
1d743b8b
EA
97 if (ev == NULL)
98 return;
2439b900
EA
99
100 /* find the parent event */
7338e3d4 101 (void) signal(SIGALRM, SIG_IGN);
2439b900
EA
102 for (evp = &EventQueue; *evp != NULL; evp = &(*evp)->ev_link)
103 {
104 if (*evp == ev)
105 break;
106 }
107
108 /* now remove it */
6d06102a
EA
109 if (*evp != NULL)
110 {
111 *evp = ev->ev_link;
611b763d 112 free((char *) ev);
6d06102a 113 }
f2f69820
EA
114
115 /* restore clocks and pick up anything spare */
116 tick();
2439b900
EA
117}
118\f/*
78eeba87
EA
119** TICK -- take a clock tick
120**
2439b900 121** Called by the alarm clock. This routine runs events as needed.
78eeba87
EA
122**
123** Parameters:
124** none.
125**
126** Returns:
2439b900 127** none.
78eeba87
EA
128**
129** Side Effects:
2439b900 130** calls the next function in EventQueue.
78eeba87
EA
131*/
132
dc7f9678 133static void
78eeba87
EA
134tick()
135{
0908f182 136 register time_t now;
2439b900 137 register EVENT *ev;
8ff78b51 138 int mypid = getpid();
2439b900 139
7338e3d4
EA
140 (void) signal(SIGALRM, SIG_IGN);
141 (void) alarm(0);
0908f182 142 now = curtime();
2439b900 143
aa4ef64d 144 if (tTd(5, 4))
2439b900 145 printf("tick: now=%ld\n", now);
2439b900 146
88e17a34 147 while ((ev = EventQueue) != NULL &&
8ff78b51 148 (ev->ev_time <= now || ev->ev_pid != mypid))
2439b900 149 {
ce7cfd4c
EA
150 int (*f)();
151 int arg;
152 int pid;
f2f69820 153
2439b900
EA
154 /* process the event on the top of the queue */
155 ev = EventQueue;
156 EventQueue = EventQueue->ev_link;
aa4ef64d 157 if (tTd(5, 6))
f5d25d7b
EA
158 printf("tick: ev=%x, func=%x, arg=%d, pid=%d\n", ev,
159 ev->ev_func, ev->ev_arg, ev->ev_pid);
f2f69820
EA
160
161 /* we must be careful in here because ev_func may not return */
7338e3d4 162 (void) signal(SIGALRM, tick);
db8c40d3
EA
163#ifdef SIGVTALRM
164 /* reset 4.2bsd signal mask to allow future alarms */
165 (void) sigsetmask(sigblock(0) & ~sigmask(SIGALRM));
f3d8f6d6 166#endif /* SIGVTALRM */
db8c40d3 167
f2f69820 168 f = ev->ev_func;
ce7cfd4c
EA
169 arg = ev->ev_arg;
170 pid = ev->ev_pid;
611b763d 171 free((char *) ev);
ce7cfd4c 172 if (pid != getpid())
f5d25d7b 173 continue;
f2f69820
EA
174 if (EventQueue != NULL)
175 {
176 if (EventQueue->ev_time > now)
77b16ff1 177 (void) alarm((unsigned) (EventQueue->ev_time - now));
f2f69820 178 else
0908f182 179 (void) alarm(3);
f2f69820 180 }
ce7cfd4c 181 (*f)(arg);
f2f69820 182 (void) alarm(0);
0908f182 183 now = curtime();
2439b900 184 }
7338e3d4 185 (void) signal(SIGALRM, tick);
0908f182 186 if (EventQueue != NULL)
77b16ff1 187 (void) alarm((unsigned) (EventQueue->ev_time - now));
78eeba87 188}
c4442979
EA
189\f/*
190** SLEEP -- a version of sleep that works with this stuff
191**
192** Because sleep uses the alarm facility, I must reimplement
193** it here.
194**
195** Parameters:
196** intvl -- time to sleep.
197**
198** Returns:
199** none.
200**
201** Side Effects:
202** waits for intvl time. However, other events can
203** be run during that interval.
204*/
205
206static bool SleepDone;
207
208sleep(intvl)
901911f8 209 unsigned int intvl;
c4442979 210{
0df908a9 211 static int endsleep();
c4442979 212
1d743b8b
EA
213 if (intvl == 0)
214 return;
c4442979 215 SleepDone = FALSE;
77b16ff1 216 (void) setevent((time_t) intvl, endsleep, 0);
c4442979
EA
217 while (!SleepDone)
218 pause();
219}
220
221static
222endsleep()
223{
224 SleepDone = TRUE;
225}